1 /*
2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
3 *
4 * All source code herein is the property of Volition, Inc. You may not sell
5 * or otherwise commercially exploit the source or things you created based on the
6 * source.
7 *
8 */
9
10 // ModifyVariableDlg.cpp : implementation file
11 //
12
13 #include "stdafx.h"
14 #include "FRED.h"
15 #include "ModifyVariableDlg.h"
16 #include "parse/sexp.h"
17
18 #ifdef _DEBUG
19 #undef THIS_FILE
20 static char THIS_FILE[] = __FILE__;
21 #endif
22
23 #define NO_RESET_FOCUS 0
24 #define RESET_FOCUS 1
25
26
27 /////////////////////////////////////////////////////////////////////////////
28 // CModifyVariableDlg dialog
29
CModifyVariableDlg(CWnd * pParent)30 CModifyVariableDlg::CModifyVariableDlg(CWnd* pParent /*=NULL*/)
31 : CDialog(CModifyVariableDlg::IDD, pParent)
32 {
33 //{{AFX_DATA_INIT(CModifyVariableDlg)
34 m_default_value = _T("");
35 m_cur_variable_name = _T("");
36 //}}AFX_DATA_INIT
37 }
38
39
DoDataExchange(CDataExchange * pDX)40 void CModifyVariableDlg::DoDataExchange(CDataExchange* pDX)
41 {
42 CDialog::DoDataExchange(pDX);
43 //{{AFX_DATA_MAP(CModifyVariableDlg)
44 DDX_Text(pDX, IDC_MODIFY_DEFAULT_VALUE, m_default_value);
45 DDV_MaxChars(pDX, m_default_value, 31);
46 DDX_CBString(pDX, IDC_MODIFY_VARIABLE_NAME, m_cur_variable_name);
47 DDV_MaxChars(pDX, m_cur_variable_name, 31);
48 //}}AFX_DATA_MAP
49 }
50
51
BEGIN_MESSAGE_MAP(CModifyVariableDlg,CDialog)52 BEGIN_MESSAGE_MAP(CModifyVariableDlg, CDialog)
53 //{{AFX_MSG_MAP(CModifyVariableDlg)
54 ON_BN_CLICKED(ID_DELETE_VARIABLE, OnDeleteVariable)
55 ON_BN_CLICKED(IDC_TYPE_STRING, OnTypeString)
56 ON_BN_CLICKED(IDC_TYPE_NUMBER, OnTypeNumber)
57 ON_BN_CLICKED(IDC_TYPE_PLAYER_PERSISTENT, OnTypePlayerPersistent)
58 ON_BN_CLICKED(IDC_TYPE_CAMPAIGN_PERSISTENT, OnTypeCampaignPersistent)
59 ON_BN_CLICKED(IDC_TYPE_NETWORK_VARIABLE, OnTypeNetworkVariable)
60 ON_CBN_SELCHANGE(IDC_MODIFY_VARIABLE_NAME, OnSelchangeModifyVariableName)
61 ON_CBN_EDITCHANGE(IDC_MODIFY_VARIABLE_NAME, OnEditchangeModifyVariableName)
62 ON_EN_KILLFOCUS(IDC_MODIFY_DEFAULT_VALUE, OnKillfocusModifyDefaultValue)
63 ON_CBN_DROPDOWN(IDC_MODIFY_VARIABLE_NAME, OnDropdownModifyVariableName)
64 //}}AFX_MSG_MAP
65 END_MESSAGE_MAP()
66
67 /////////////////////////////////////////////////////////////////////////////
68 // CModifyVariableDlg message handlers
69
70 // Maybe delete variable
71 void CModifyVariableDlg::OnDeleteVariable()
72 {
73 CString temp_name;
74 int rval;
75
76 // Check for name change
77 CComboBox *cbox = (CComboBox *) GetDlgItem(IDC_MODIFY_VARIABLE_NAME);
78 cbox->GetWindowText(temp_name);
79
80 // Can't delete. Name has been changed
81 if ( stricmp(Sexp_variables[get_sexp_var_index()].variable_name, temp_name) ) {
82 MessageBox("Can not delete variable. Name has been changed.");
83 return;
84 }
85
86 char message[128] = "Can not delete variable.";
87 if (!IsChangeSafe(message)) {
88 return;
89 }
90
91 // maybe delete variable
92 rval = MessageBox("This will permanantly delete the variable. Do you want to continue?", NULL, MB_OKCANCEL);
93
94 if (rval == IDOK) {
95 // delete variable and exit
96 m_deleted = true;
97 // next statement does UpdataData(TRUE);
98 CDialog::OnOK();
99 }
100 }
101
102 // Karajorma - Checks whether it is safe to delete or modify this string
IsChangeSafe(char * message)103 bool CModifyVariableDlg::IsChangeSafe(char *message)
104 {
105 // Can't as there are SEXPs using it.
106 int num_counts = m_p_sexp_tree->get_variable_count(Sexp_variables[get_sexp_var_index()].variable_name);
107 if (num_counts > 0) {
108 char buffer[256];
109 sprintf(buffer, "%s Used in %d SEXP(s).", message, num_counts);
110 MessageBox(buffer);
111 return false;
112 }
113
114 // Can't as it is used in the team loadout
115 num_counts = m_p_sexp_tree->get_loadout_variable_count(get_sexp_var_index());
116 if (num_counts > 0) {
117 char buffer[256];
118 sprintf(buffer, "%s Used in %d location(s) in loadout.", message, num_counts);
119 MessageBox(buffer);
120 return false;
121 }
122
123 return true;
124 }
125
126 // Set type to string
OnTypeString()127 void CModifyVariableDlg::OnTypeString()
128 {
129 // check if type actually modified
130 if (m_type_number == true) {
131
132 // Don't allow type change if in use.
133 char message[128] = "Can not modify variable type.";
134 if (!IsChangeSafe(message)) {
135 m_type_number = true;
136 m_modified_type = false;
137 set_variable_type();
138 return;
139 }
140
141 // keep track if type is really changed
142 if (m_modified_type == true) {
143 m_modified_type = false;
144 } else {
145 m_modified_type = true;
146 }
147 }
148 m_type_number = false;
149 set_variable_type();
150 }
151
152 // Set type to number
OnTypeNumber()153 void CModifyVariableDlg::OnTypeNumber()
154 {
155 // check if type actually modified
156 if (m_type_number == false) {
157
158 // Don't allow type change if in use.
159 char message[128] = "Can not modify variable type.";
160 if (!IsChangeSafe(message)) {
161 m_type_number = false;
162 m_modified_type = false;
163 set_variable_type();
164 return;
165 }
166
167 // keep track if type is really changed
168 if (m_modified_type == true) {
169 m_modified_type = false;
170 } else {
171 m_modified_type = true;
172 }
173 }
174 m_type_number = true;
175 set_variable_type();
176 }
177
178 // set player persistence
OnTypePlayerPersistent()179 void CModifyVariableDlg::OnTypePlayerPersistent()
180 {
181 m_type_player_persistent = ((CButton *) GetDlgItem(IDC_TYPE_PLAYER_PERSISTENT))->GetCheck() ? true : false;
182
183 // keep track if type is really changed (ugh - just force it to be always changed)
184 m_modified_persistence = true;
185
186 if (m_type_player_persistent)
187 m_type_campaign_persistent = false;
188
189 set_variable_type();
190 }
191
192 // set campaign persistence
OnTypeCampaignPersistent()193 void CModifyVariableDlg::OnTypeCampaignPersistent()
194 {
195 m_type_campaign_persistent = ((CButton *) GetDlgItem(IDC_TYPE_CAMPAIGN_PERSISTENT))->GetCheck() ? true : false;
196
197 // keep track if type is really changed (ugh - just force it to be always changed)
198 m_modified_persistence = true;
199
200 if (m_type_campaign_persistent)
201 m_type_player_persistent = false;
202
203 set_variable_type();
204 }
205
OnTypeNetworkVariable()206 void CModifyVariableDlg::OnTypeNetworkVariable()
207 {
208 m_type_network_variable = ((CButton *) GetDlgItem(IDC_TYPE_NETWORK_VARIABLE))->GetCheck() ? true : false;
209
210 m_modified_type = true;
211
212 set_variable_type();
213 }
214
OnSelchangeModifyVariableName()215 void CModifyVariableDlg::OnSelchangeModifyVariableName()
216 {
217 CComboBox *cbox = (CComboBox *) GetDlgItem(IDC_MODIFY_VARIABLE_NAME);
218
219 // get index of current selection
220 int index = cbox->GetCurSel();
221
222 // check an item was actually selected, and not outside the box
223 if (index == CB_ERR) {
224 return;
225 }
226
227 // check if another has been modified
228 if (m_modified_type || m_modified_persistence || m_modified_name || m_modified_value) {
229
230 // Don't send message if changing to self
231 if (index != m_combo_last_modified_index) {
232 MessageBox("Can only modify one variable.");
233 }
234
235 //reset focus to current
236 cbox->SetCurSel(m_combo_last_modified_index);
237 return;
238 }
239
240 m_combo_last_modified_index = index;
241
242 // Get index into sexp_variables
243 int sexp_variable_index = get_sexp_var_index();
244
245 // Set new type for selection
246 m_type_number = ((Sexp_variables[sexp_variable_index].type & SEXP_VARIABLE_NUMBER) != 0) ? true : false;
247 m_type_campaign_persistent = ((Sexp_variables[sexp_variable_index].type & SEXP_VARIABLE_CAMPAIGN_PERSISTENT) != 0) ? true : false;
248 m_type_player_persistent = ((Sexp_variables[sexp_variable_index].type & SEXP_VARIABLE_PLAYER_PERSISTENT) != 0) ? true : false;
249 m_type_network_variable = ((Sexp_variables[sexp_variable_index].type & SEXP_VARIABLE_NETWORK) != 0) ? true : false;
250 set_variable_type();
251
252 // Set new default value for selection
253 if (sexp_variable_index > -1) {
254 CEdit *edit = (CEdit *) GetDlgItem(IDC_MODIFY_DEFAULT_VALUE);
255 edit->SetWindowText(Sexp_variables[sexp_variable_index].text);
256 }
257 }
258
259 // Check if variable name has changed from Sexp_variables[].varaible name
OnEditchangeModifyVariableName()260 void CModifyVariableDlg::OnEditchangeModifyVariableName()
261 {
262 // Do string compare to check for change
263 CString temp_name;
264
265 // Get current variable name
266 CComboBox *cbox = (CComboBox *) GetDlgItem(IDC_MODIFY_VARIABLE_NAME);
267 cbox->GetWindowText(temp_name);
268
269 // Check if variable name is modified
270 if ( strcmp(Sexp_variables[get_sexp_var_index()].variable_name, temp_name) ) {
271 m_modified_name = true;
272 } else {
273 m_modified_name = false;
274 }
275 }
276
OnInitDialog()277 BOOL CModifyVariableDlg::OnInitDialog()
278 {
279 CDialog::OnInitDialog();
280
281 int i, box_index;
282 // Init combo box and translation table from combo box to sexp_varaibles
283 CComboBox *cbox = (CComboBox *) GetDlgItem(IDC_MODIFY_VARIABLE_NAME);
284 cbox->ResetContent();
285
286 for (i=0; i<MAX_SEXP_VARIABLES; i++) {
287 m_translate_combo_to_sexp[i] = -1;
288 }
289
290 // initialize list -- Box is set to *not* sort
291 for (i=0; i<MAX_SEXP_VARIABLES; i++) {
292 if ((Sexp_variables[i].type & SEXP_VARIABLE_SET) && !(Sexp_variables[i].type & SEXP_VARIABLE_BLOCK)){
293 box_index = cbox->AddString(Sexp_variables[i].variable_name);
294
295 // check no error
296 if ( !((box_index == CB_ERR) || (box_index == CB_ERRSPACE)) ) {
297 m_translate_combo_to_sexp[box_index] = i;
298 }
299 }
300 }
301
302 // Exit gracefully if nothing added to combo box
303 if (cbox->GetCount() == 0) {
304 Int3(); // this should not happen
305 OnCancel();
306 }
307
308 int last_modified = 0;
309 // Set current variable
310 if (m_start_index > -1) {
311 for (i=0; i<MAX_SEXP_VARIABLES; i++) {
312 if (m_translate_combo_to_sexp[i] == m_start_index) {
313 last_modified = i;
314 break;
315 }
316 }
317 }
318
319 m_combo_last_modified_index = last_modified;
320 cbox->SetCurSel(last_modified);
321
322 // Set the default value
323 if (m_translate_combo_to_sexp[last_modified] > -1) {
324 CEdit *edit = (CEdit *) GetDlgItem(IDC_MODIFY_DEFAULT_VALUE);
325 edit->SetWindowText(Sexp_variables[m_translate_combo_to_sexp[last_modified]].text);
326 }
327
328 // Set old variable name
329 m_old_var_name = Sexp_variables[m_translate_combo_to_sexp[last_modified]].variable_name;
330
331 // Set type
332 m_type_number = ((Sexp_variables[last_modified].type & SEXP_VARIABLE_NUMBER) != 0) ? true : false;
333 m_type_campaign_persistent = ((Sexp_variables[last_modified].type & SEXP_VARIABLE_CAMPAIGN_PERSISTENT) != 0) ? true : false;
334 m_type_player_persistent = ((Sexp_variables[last_modified].type & SEXP_VARIABLE_PLAYER_PERSISTENT) != 0) ? true : false;
335 m_type_network_variable = ((Sexp_variables[last_modified].type & SEXP_VARIABLE_NETWORK) != 0) ? true : false;
336 set_variable_type();
337
338 // keep track of changes
339 m_modified_name = false;
340 m_modified_value = false;
341 m_modified_type = false;
342 m_modified_persistence = false;
343 m_deleted = false;
344 m_do_modify = false;
345
346 m_data_validated = false;
347 m_var_name_validated = false;
348
349
350 return TRUE; // return TRUE unless you set the focus to a control
351 // EXCEPTION: OCX Property Pages should return FALSE
352 }
353
set_variable_type()354 void CModifyVariableDlg::set_variable_type()
355 {
356 // get buttons
357 CButton *button_string = (CButton *) GetDlgItem(IDC_TYPE_STRING);
358 CButton *button_number = (CButton *) GetDlgItem(IDC_TYPE_NUMBER);
359
360 // assign state
361 button_number->SetCheck( m_type_number);
362 button_string->SetCheck(!m_type_number);
363
364 ((CButton *) GetDlgItem(IDC_TYPE_CAMPAIGN_PERSISTENT))->SetCheck(m_type_campaign_persistent);
365 ((CButton *) GetDlgItem(IDC_TYPE_PLAYER_PERSISTENT))->SetCheck(m_type_player_persistent);
366 ((CButton *) GetDlgItem(IDC_TYPE_NETWORK_VARIABLE))->SetCheck(m_type_network_variable);
367 }
368
OnOK()369 void CModifyVariableDlg::OnOK()
370 {
371 CString temp_data;
372
373 // Validate data
374 CEdit *edit = (CEdit *) GetDlgItem(IDC_MODIFY_DEFAULT_VALUE);
375 edit->GetWindowText(temp_data);
376
377 // validate data
378 validate_data(temp_data, RESET_FOCUS);
379 if (m_data_validated) {
380 // Don't get OnKillfocusModifyDefaultValue when ok
381 if (!m_modified_value) {
382 if ( strcmp(Sexp_variables[get_sexp_var_index()].text, temp_data) ) {
383 m_modified_value = true;
384 }
385 }
386
387 // validate variable name
388 validate_var_name(RESET_FOCUS);
389 if (m_var_name_validated) {
390
391 // maybe set m_do_modify -- this is needed. compare with OnCancel()
392 if (m_modified_name || m_modified_persistence || m_modified_value || m_modified_type) {
393 m_do_modify = true;
394 }
395 CDialog::OnOK();
396 }
397 }
398 }
399
OnKillfocusModifyDefaultValue()400 void CModifyVariableDlg::OnKillfocusModifyDefaultValue()
401 {
402 // Do string compare to check for change
403 CString temp_data;
404
405 CEdit *edit = (CEdit *) GetDlgItem(IDC_MODIFY_DEFAULT_VALUE);
406 edit->GetWindowText(temp_data);
407
408 if ( strcmp(Sexp_variables[get_sexp_var_index()].text, temp_data) ) {
409 m_modified_value = true;
410 } else {
411 m_modified_value = false;
412 }
413 }
414
415 // validate data
416 // check (1) zero length (2) invalid chars (3) value if numberf
validate_data(CString & temp_data,int set_focus)417 void CModifyVariableDlg::validate_data(CString &temp_data, int set_focus)
418 {
419 // display invalid data message
420 bool message = false;
421 char message_text[256];
422
423 // check length > 0
424 int length = strlen(temp_data);
425 if (length == 0) {
426 strcpy_s(message_text, "Invalid Default Value");
427 message = true;
428
429 } else if (m_type_number) {
430 // check if string and str(atoi(stri)) are same
431 int temp_num = atoi(temp_data);
432 char buf[TOKEN_LENGTH];
433 sprintf(buf, "%d", temp_num);
434
435 if ( stricmp(buf, temp_data) ) {
436 message = true;
437 strcpy_s(message_text, "Invalid Default Value");
438 } else {
439 message = false;
440 }
441 }
442
443 // check for invalid characters
444 int rval = strcspn(temp_data, "@()");
445 if (rval != length) {
446 message = true;
447 sprintf(message_text, "Invalid char '%c' in Default Value", temp_data[rval]);
448 }
449
450 // display message
451 if ( message ) {
452 m_data_validated = false;
453 MessageBox(message_text);
454
455 // reset focus
456 if (set_focus == RESET_FOCUS) {
457 CEdit *edit = (CEdit *) GetDlgItem(IDC_MODIFY_DEFAULT_VALUE);
458 edit->SetFocus();
459 edit->SetSel(0, -1);
460 }
461 }
462
463 // string always ok, numbers if no message
464 m_data_validated = !message;
465 }
466
467 // validate variable name
468 // check (1) zero length (2) invalid chars (3) already in use
validate_var_name(int set_focus)469 void CModifyVariableDlg::validate_var_name(int set_focus)
470 {
471 CString temp_name;
472 CComboBox *cbox = (CComboBox *) GetDlgItem(IDC_MODIFY_VARIABLE_NAME);
473 cbox->GetWindowText(temp_name);
474
475 int cur_sel = cbox->GetCurSel();
476 m_old_var_name = Sexp_variables[m_translate_combo_to_sexp[cur_sel]].variable_name;
477
478 // display invalid data message
479 bool message = false;
480 char message_text[256];
481
482 // check length > 0
483 int length = strlen(temp_name);
484 if (length == 0) {
485 strcpy_s(message_text, "Invalid Variable Name");
486 message = true;
487 } else {
488
489 // check for invalid characters
490 int rval = strcspn(temp_name, "@()");
491 if (rval != length) {
492 message = true;
493 sprintf(message_text, "Invalid char '%c' in Variable Name", temp_name[rval]);
494 } else {
495 int index = get_index_sexp_variable_name(temp_name);
496
497 // if not a new name and not start name
498 if ( (index != -1) && (index != m_translate_combo_to_sexp[m_combo_last_modified_index]) ) {
499 message = true;
500 strcpy_s(message_text, "Variable Name already in use");
501 }
502 }
503 }
504
505 // display message
506 if ( message ) {
507 MessageBox(message_text);
508
509 // reset focus
510 if (set_focus == RESET_FOCUS) {
511 cbox->SetFocus();
512 }
513 }
514
515 // set var_name_validated
516 m_var_name_validated = !message;
517 }
518
519
get_sexp_var_index()520 int CModifyVariableDlg::get_sexp_var_index()
521 {
522 int index = m_translate_combo_to_sexp[m_combo_last_modified_index];
523 Assert( (index >= 0) && (index < MAX_SEXP_VARIABLES) );
524
525 return index;
526 }
527
528 // Reset text in drop down list
OnDropdownModifyVariableName()529 void CModifyVariableDlg::OnDropdownModifyVariableName()
530 {
531 CString temp_name;
532
533 // Get current variable name
534 CComboBox *cbox = (CComboBox *) GetDlgItem(IDC_MODIFY_VARIABLE_NAME);
535 cbox->GetWindowText(temp_name);
536
537 // Reset combo box text
538 int rval;
539 rval = cbox->InsertString(m_combo_last_modified_index, temp_name);
540 if ( (rval == CB_ERR) || (rval == CB_ERRSPACE) ) {
541 AfxMessageBox("An internal error has occured.");
542 OnCancel();
543 }
544 cbox->DeleteString(m_combo_last_modified_index+1);
545
546 cbox->SetCurSel(m_combo_last_modified_index);
547 }
548