]> icculus.org git repositories - taylor/freespace2.git/blob - src/fred2/debriefingeditordlg.cpp
The Great Newline Fix
[taylor/freespace2.git] / src / fred2 / debriefingeditordlg.cpp
1 /*
2  * $Logfile: /Freespace2/code/FRED2/DebriefingEditorDlg.cpp $
3  * $Revision$
4  * $Date$
5  * $Author$
6  *
7  * Debriefing editor dialog.  Used to edit mission debriefings of course.
8  *
9  * $Log$
10  * Revision 1.2  2002/05/07 03:16:44  theoddone33
11  * The Great Newline Fix
12  *
13  * Revision 1.1.1.1  2002/05/03 03:28:08  root
14  * Initial import.
15  *
16  * 
17  * 2     10/07/98 6:28p Dave
18  * Initial checkin. Renamed all relevant stuff to be Fred2 instead of
19  * Fred. Globalized mission and campaign file extensions. Removed Silent
20  * Threat specific code.
21  * 
22  * 1     10/07/98 3:01p Dave
23  * 
24  * 1     10/07/98 3:00p Dave
25  * 
26  * 20    7/07/98 2:09p Hoffoss
27  * Fixed bug where sexp for debriefing stages get cleared when inserting
28  * or deleting stages.
29  * 
30  * 19    4/30/98 8:23p John
31  * Fixed some bugs with Fred caused by my new cfile code.
32  * 
33  * 18    4/22/98 9:56a Sandeep
34  * 
35  * 17    4/20/98 4:40p Hoffoss
36  * Added a button to 4 editors to play the chosen wave file.
37  * 
38  * 16    4/17/98 1:41p Allender
39  * took out function calls in NDEBUG mode
40  * 
41  * 15    4/06/98 10:43a John
42  * Fixed bugs with inserting/deleting stages
43  * 
44  * 14    4/03/98 12:39p Hoffoss
45  * Changed starting directory for browse buttons in several editors.
46  * 
47  * 13    4/03/98 11:34a John
48  * Fixed the stuff I broke in Fred from the new breifing
49  * 
50  * 12    3/17/98 2:06p Hoffoss
51  * Made enter key not close the dialog box (default windows behavior, even
52  * when no ok button.  Talk about stupid. :)
53  * 
54  * 11    2/09/98 9:25p Allender
55  * team v team support.  multiple pools and breifings
56  * 
57  * 10    2/04/98 4:32p Allender
58  * support for multiple briefings and debriefings.  Changes to mission
59  * type (now a bitfield).  Bitfield defs for multiplayer modes
60  * 
61  * 9     1/02/98 3:29p Duncan
62  * Fixed bug with sexp tree freeing.
63  * 
64  * 8     11/10/97 12:09p Johnson
65  * Fixed sexp free error in debriefing editor.
66  * 
67  * 7     11/10/97 11:58a Johnson
68  * Added support to debriefing editor for "press cancel to go to reference
69  * of sexp".
70  * 
71  * 6     10/28/97 6:07p Jasen
72  * Added some debugging code to detect sexp leaks.  Looks there are some I
73  * will need to investigate more.
74  * 
75  * 5     10/27/97 2:06p Hoffoss
76  * Fixed editor to allow correct character limit for recommendation text.
77  * 
78  * 4     10/14/97 12:06p Hoffoss
79  * Recoded debriefing editor to utilize new format.
80  * 
81  * 3     10/14/97 10:35a Hoffoss
82  * Hacked the hell out of this file to allow Fred to compile for now.
83  * Next step is to fix it all.
84  * 
85  * 2     7/08/97 2:03p Hoffoss
86  * Debriefing editor coded and implemented.
87  *
88  * $NoKeywords: $
89  */
90
91 #include "stdafx.h"
92 #include <mmsystem.h>
93 #include "fred.h"
94 #include "debriefingeditordlg.h"
95 #include "freddoc.h"
96 #include "missionbriefcommon.h"
97 #include "sexp.h"
98 #include "cfile.h"
99
100 #ifdef _DEBUG
101 #define new DEBUG_NEW
102 #undef THIS_FILE
103 static char THIS_FILE[] = __FILE__;
104 #endif
105
106 /////////////////////////////////////////////////////////////////////////////
107 // debriefing_editor_dlg dialog
108
109 debriefing_editor_dlg::debriefing_editor_dlg(CWnd* pParent /*=NULL*/)
110         : CDialog(debriefing_editor_dlg::IDD, pParent)
111 {
112         //{{AFX_DATA_INIT(debriefing_editor_dlg)
113         m_text = _T("");
114         m_voice = _T("");
115         m_stage_title = _T("");
116         m_rec_text = _T("");
117         m_current_debriefing = -1;
118         //}}AFX_DATA_INIT
119
120         modified = 0;
121         m_cur_stage = 0;
122         m_last_stage = -1;
123         select_sexp_node = -1;
124 }
125
126 void debriefing_editor_dlg::DoDataExchange(CDataExchange* pDX)
127 {
128         CDialog::DoDataExchange(pDX);
129         //{{AFX_DATA_MAP(debriefing_editor_dlg)
130         DDX_Control(pDX, IDC_TREE, m_tree);
131         DDX_Text(pDX, IDC_TEXT, m_text);
132         DDX_Text(pDX, IDC_VOICE, m_voice);
133         DDX_Text(pDX, IDC_STAGE_TITLE, m_stage_title);
134         DDX_Text(pDX, IDC_REC_TEXT, m_rec_text);
135         //}}AFX_DATA_MAP
136
137         DDV_MaxChars(pDX, m_text, MAX_BRIEF_LEN - 1);
138         DDV_MaxChars(pDX, m_voice, MAX_FILENAME_LEN - 1);
139         DDV_MaxChars(pDX, m_rec_text, MAX_RECOMMENDATION_LEN - 1);
140 }
141
142 BEGIN_MESSAGE_MAP(debriefing_editor_dlg, CDialog)
143         //{{AFX_MSG_MAP(debriefing_editor_dlg)
144         ON_BN_CLICKED(IDC_NEXT, OnNext)
145         ON_BN_CLICKED(IDC_PREV, OnPrev)
146         ON_BN_CLICKED(IDC_BROWSE, OnBrowse)
147         ON_BN_CLICKED(IDC_ADD_STAGE, OnAddStage)
148         ON_BN_CLICKED(IDC_DELETE_STAGE, OnDeleteStage)
149         ON_BN_CLICKED(IDC_INSERT_STAGE, OnInsertStage)
150         ON_NOTIFY(NM_RCLICK, IDC_TREE, OnRclickTree)
151         ON_NOTIFY(TVN_BEGINLABELEDIT, IDC_TREE, OnBeginlabeleditTree)
152         ON_NOTIFY(TVN_ENDLABELEDIT, IDC_TREE, OnEndlabeleditTree)
153         ON_WM_CLOSE()
154         ON_WM_INITMENU()
155         ON_BN_CLICKED(IDC_PLAY, OnPlay)
156         //}}AFX_MSG_MAP
157 END_MESSAGE_MAP()
158
159 /////////////////////////////////////////////////////////////////////////////
160 // debriefing_editor_dlg message handlers
161
162 void debriefing_editor_dlg::OnInitMenu(CMenu* pMenu)
163 {
164         int i;
165         CMenu *m;
166
167         // disable any items we should disable
168         m = pMenu->GetSubMenu(0);
169
170         // uncheck all menu items
171         for (i = 0; i < Num_teams; i++ )
172                 m->CheckMenuItem( i, MF_BYPOSITION | MF_UNCHECKED );
173
174         for ( i = Num_teams; i < MAX_TEAMS; i++ )
175                 m->EnableMenuItem(i, MF_BYPOSITION | MF_GRAYED);
176
177
178         // put a check next to the currently selected item
179         m->CheckMenuItem(m_current_debriefing, MF_BYPOSITION | MF_CHECKED );
180
181         CDialog::OnInitMenu(pMenu);
182 }
183
184 BOOL debriefing_editor_dlg::OnInitDialog()
185 {
186         int i, n;
187
188         CDialog::OnInitDialog();
189         m_play_bm.LoadBitmap(IDB_PLAY);
190         ((CButton *) GetDlgItem(IDC_PLAY)) -> SetBitmap(m_play_bm);
191
192         m_current_debriefing = 0;
193         UpdateData(FALSE);
194
195         Debriefing = &Debriefings[m_current_debriefing];
196
197         m_tree.link_modified(&modified);  // provide way to indicate trees are modified in dialog
198         n = m_tree.select_sexp_node = select_sexp_node;
199         select_sexp_node = -1;
200         if (n != -1) {
201                 for (i=0; i<Debriefing->num_stages; i++)
202                         if (query_node_in_sexp(n, Debriefing->stages[i].formula))
203                                 break;
204
205                 if (i < Debriefing->num_stages) {
206                         m_cur_stage = i;
207                         update_data();
208                         GetDlgItem(IDC_TREE) -> SetFocus();
209                         m_tree.hilite_item(m_tree.select_sexp_node);
210                         set_modified();
211                         return FALSE;
212                 }
213         }
214
215         update_data();
216         set_modified();
217
218         // hard coded stuff to deal with the multiple briefings per mission.
219
220         return TRUE;
221 }
222
223 void debriefing_editor_dlg::update_data(int update)
224 {
225         int enable, save_debriefing;
226         debrief_stage *ptr;
227
228         save_debriefing = m_current_debriefing;
229
230         if (update)
231                 UpdateData(TRUE);
232
233         // based on the game type, enable the multiple briefings combo box (or disable it)
234
235         // set up the pointer to the briefing that we are editing
236         if ( save_debriefing != m_current_debriefing )
237                 Debriefing = &Debriefings[save_debriefing];
238         else
239                 Debriefing = &Debriefings[m_current_debriefing];
240
241         if (m_last_stage >= 0) {
242                 ptr = &Debriefing->stages[m_last_stage];
243                 if (ptr->formula >= 0)
244                         free_sexp2(ptr->formula);
245
246                 ptr->formula = m_tree.save_tree();
247                 deconvert_multiline_string(ptr->new_text, m_text, MAX_DEBRIEF_LEN);
248                 deconvert_multiline_string(ptr->new_recommendation_text, m_rec_text, MAX_RECOMMENDATION_LEN);
249                 string_copy(ptr->voice, m_voice, MAX_FILENAME_LEN);
250         }
251
252         // now get new stage data
253         if ((m_cur_stage >= 0) && (m_cur_stage < Debriefing->num_stages)) {
254                 ptr = &Debriefing->stages[m_cur_stage];
255                 m_stage_title.Format("Stage %d of %d", m_cur_stage + 1, Debriefing->num_stages);
256                 m_tree.load_tree(ptr->formula);
257                 m_text = convert_multiline_string(ptr->new_text);
258                 m_rec_text = convert_multiline_string(ptr->new_recommendation_text);
259                 m_voice = ptr->voice;
260                 enable = TRUE;
261
262         } else {
263                 m_stage_title = _T("No stages");
264                 m_tree.clear_tree();
265                 m_text = _T("");
266                 m_rec_text = _T("");
267                 m_voice = _T("");
268                 enable = FALSE;
269                 m_cur_stage = -1;
270         }
271
272         if (m_cur_stage == Debriefing->num_stages - 1)
273                 GetDlgItem(IDC_NEXT) -> EnableWindow(FALSE);
274         else
275                 GetDlgItem(IDC_NEXT) -> EnableWindow(enable);
276
277         if (m_cur_stage)
278                 GetDlgItem(IDC_PREV) -> EnableWindow(enable);
279         else
280                 GetDlgItem(IDC_PREV) -> EnableWindow(FALSE);
281
282         if (Debriefing->num_stages >= MAX_DEBRIEF_STAGES)
283                 GetDlgItem(IDC_ADD_STAGE) -> EnableWindow(FALSE);
284         else
285                 GetDlgItem(IDC_ADD_STAGE) -> EnableWindow(TRUE);
286
287         if (Debriefing->num_stages) {
288                 GetDlgItem(IDC_DELETE_STAGE) -> EnableWindow(enable);
289                 GetDlgItem(IDC_INSERT_STAGE) -> EnableWindow(enable);
290
291         } else {
292                 GetDlgItem(IDC_DELETE_STAGE) -> EnableWindow(FALSE);
293                 GetDlgItem(IDC_INSERT_STAGE) -> EnableWindow(FALSE);
294         }
295
296         GetDlgItem(IDC_VOICE) -> EnableWindow(enable);
297         GetDlgItem(IDC_BROWSE) -> EnableWindow(enable);
298         GetDlgItem(IDC_TEXT) -> EnableWindow(enable);
299         GetDlgItem(IDC_REC_TEXT) -> EnableWindow(enable);
300         GetDlgItem(IDC_TREE) -> EnableWindow(enable);
301
302         m_last_stage = m_cur_stage;
303         UpdateData(FALSE);
304
305         #ifndef NDEBUG
306         count_free_sexp_nodes();
307         #endif
308 }
309
310 void debriefing_editor_dlg::OnNext() 
311 {
312         m_cur_stage++;
313         update_data();
314 }
315
316 void debriefing_editor_dlg::OnPrev() 
317 {
318         m_cur_stage--;
319         update_data();
320 }
321
322 void debriefing_editor_dlg::OnBrowse() 
323 {
324         int z;
325         CString name;
326
327         UpdateData(TRUE);
328
329         if (The_mission.game_type & MISSION_TYPE_TRAINING)
330                 z = cfile_push_chdir(CF_TYPE_VOICE_TRAINING);
331         else
332                 z = cfile_push_chdir(CF_TYPE_VOICE_DEBRIEFINGS);
333
334         CFileDialog dlg(TRUE, "wav", NULL, OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR,
335                 "Wave Files (*.wav)|*.wav||");
336
337         if (dlg.DoModal() == IDOK) {
338                 m_voice = dlg.GetFileName();
339                 UpdateData(FALSE);
340         }
341
342         if (!z)
343                 cfile_pop_dir();
344 }
345
346 void debriefing_editor_dlg::OnAddStage() 
347 {
348         int i;
349
350         if (Debriefing->num_stages >= MAX_DEBRIEF_STAGES)
351                 return;
352
353         m_cur_stage = i = Debriefing->num_stages++;
354         copy_stage(i - 1, i, 1);
355         update_data(1);
356 }
357
358 void debriefing_editor_dlg::OnDeleteStage() 
359 {
360         int i, z;
361
362         if (m_cur_stage < 0)
363                 return;
364         
365         Assert(Debriefing->num_stages);
366         z = m_cur_stage;
367         m_cur_stage = -1;
368         update_data(1);
369         for (i=z+1; i<Debriefing->num_stages; i++) {
370                 copy_stage(i, i - 1);
371         }
372
373         Debriefing->num_stages--;
374         m_cur_stage = z;
375         if (m_cur_stage >= Debriefing->num_stages)
376                 m_cur_stage = Debriefing->num_stages - 1;
377
378         update_data(0);
379 }
380
381 void debriefing_editor_dlg::OnInsertStage() 
382 {
383         int i, z;
384
385         if (Debriefing->num_stages >= MAX_DEBRIEF_STAGES)
386                 return;
387
388         if (!Debriefing->num_stages) {
389                 OnAddStage();
390                 return;
391         }
392
393         z = m_cur_stage;
394         m_cur_stage = -1;
395         update_data(1);
396         for (i=Debriefing->num_stages; i>z; i--) {
397                 copy_stage(i - 1, i);
398         }
399
400         Debriefing->num_stages++;
401         copy_stage(z, z + 1);
402         Debriefing->stages[z].formula = -1;
403         m_cur_stage = z;
404         update_data(0);
405 }
406
407 void debriefing_editor_dlg::copy_stage(int from, int to, int clear_formula)
408 {
409         if ((from < 0) || (from >= Debriefing->num_stages)) {
410                 strcpy(Debriefing->stages[to].new_text, "<Text here>");
411                 strcpy(Debriefing->stages[to].voice, "none.wav");
412                 Debriefing->stages[to].formula = -1;
413                 return;
414         }
415
416         
417         if (clear_formula)
418                 Debriefing->stages[to].formula = -1;
419         else
420                 Debriefing->stages[to].formula = Debriefing->stages[from].formula;
421
422         strcpy( Debriefing->stages[to].new_text, Debriefing->stages[from].new_text );
423         strcpy( Debriefing->stages[to].voice, Debriefing->stages[from].voice );
424         strcpy( Debriefing->stages[to].new_recommendation_text, Debriefing->stages[from].new_recommendation_text );
425 }
426
427 void debriefing_editor_dlg::OnRclickTree(NMHDR* pNMHDR, LRESULT* pResult) 
428 {
429         m_tree.right_clicked(); 
430         *pResult = 0;
431 }
432
433 void debriefing_editor_dlg::OnBeginlabeleditTree(NMHDR* pNMHDR, LRESULT* pResult) 
434 {
435         TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;
436
437         if (m_tree.edit_label(pTVDispInfo->item.hItem) == 1)    {
438                 *pResult = 0;
439                 modified = 1;
440
441         } else
442                 *pResult = 1;
443 }
444
445 void debriefing_editor_dlg::OnEndlabeleditTree(NMHDR* pNMHDR, LRESULT* pResult) 
446 {
447         TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;
448
449         *pResult = m_tree.end_label_edit(pTVDispInfo->item.hItem, pTVDispInfo->item.pszText);
450 }
451
452 void debriefing_editor_dlg::OnClose() 
453 {
454         m_cur_stage = -1;
455         update_data(1);
456         CDialog::OnClose();
457 }
458
459 void debriefing_editor_dlg::OnOK()
460 {
461 }
462
463 BOOL debriefing_editor_dlg::OnCommand(WPARAM wParam, LPARAM lParam) 
464 {
465         int id;
466
467         // deal with figuring out menu stuff
468         id = LOWORD(wParam);
469         if ( (id >= ID_TEAM_1) && (id < ID_TEAM_3) ) {
470                 update_data(1);
471
472                 // set the current debriefing
473                 m_current_debriefing = id - ID_TEAM_1;
474
475                 // put user back at first stage for this team (or no current stage is there are none).
476                 Debriefing = &Debriefings[m_current_debriefing];
477                 if ( Debriefing->num_stages > 0 )
478                         m_cur_stage = 0;
479                 else
480                         m_cur_stage = -1;
481
482                 m_last_stage = -1;
483                 update_data(0);
484         }
485         
486         return CDialog::OnCommand(wParam, lParam);
487 }
488
489 BOOL debriefing_editor_dlg::DestroyWindow() 
490 {
491         m_play_bm.DeleteObject();
492         return CDialog::DestroyWindow();
493 }
494
495 void debriefing_editor_dlg::OnPlay() 
496 {
497         char path[MAX_PATH_LEN + 1];
498         GetDlgItem(IDC_VOICE)->GetWindowText(m_voice);
499
500         int size, offset;
501         cf_find_file_location((char *) (LPCSTR) m_voice, CF_TYPE_ANY, path, &size, &offset );
502
503         PlaySound(path, NULL, SND_ASYNC | SND_FILENAME);
504 }
505