]> icculus.org git repositories - taylor/freespace2.git/blob - src/fred2/messageeditordlg.cpp
The Great Newline Fix
[taylor/freespace2.git] / src / fred2 / messageeditordlg.cpp
1 /*
2  * $Logfile: /Freespace2/code/FRED2/MessageEditorDlg.cpp $
3  * $Revision$
4  * $Date$
5  * $Author$
6  *
7  * Old message editor dialog box handling code.  This was designed a LONG time ago
8  * and because so much changed, I created a new one from scratch instead.  This is
9  * only around just in case it might be useful.
10  *
11  * $Log$
12  * Revision 1.2  2002/05/07 03:16:44  theoddone33
13  * The Great Newline Fix
14  *
15  * Revision 1.1.1.1  2002/05/03 03:28:08  root
16  * Initial import.
17  *
18  * 
19  * 2     10/07/98 6:28p Dave
20  * Initial checkin. Renamed all relevant stuff to be Fred2 instead of
21  * Fred. Globalized mission and campaign file extensions. Removed Silent
22  * Threat specific code.
23  * 
24  * 1     10/07/98 3:01p Dave
25  * 
26  * 1     10/07/98 3:00p Dave
27  * 
28  * 26    4/07/98 10:51a Allender
29  * remove any allied from message senders.  Make heads for mission
30  * specific messages play appropriately
31  * 
32  * 25    1/07/98 5:58p Hoffoss
33  * Combined message editor into event editor.
34  * 
35  * 24    1/06/98 4:19p Hoffoss
36  * Made message editor accept returns instead of closing dialog.
37  * 
38  * 23    12/30/97 9:39a Allender
39  * minor fixups with message editing
40  * 
41  * 22    11/17/97 4:57p Allender
42  * added persona support in FreeSpace.  A couple of new messages for
43  * message.tbl which Dan didn't have
44  * 
45  * 21    10/16/97 8:54p Duncan
46  * Fixed bug in adding new message.
47  * 
48  * 20    10/14/97 10:31a Allender
49  * disable persona field for builtin messages
50  * 
51  * 19    10/13/97 11:37a Allender
52  * added personas to message editor in Fred
53  * 
54  * 18    10/10/97 6:21p Hoffoss
55  * Put in Fred support for training object list editing.
56  * 
57  * 17    10/08/97 7:52p Hoffoss
58  * Made renaming events update all sexp references to it (added a
59  * generalized function to replace all references to a name by argument
60  * type).
61  * 
62  * 16    10/08/97 4:41p Hoffoss
63  * Changed the way message editor works.  Each message is updated
64  * perminently when you switch messages (as if ok button was pressed).
65  * 
66  * 15    9/09/97 9:19a Hoffoss
67  * Fixed bug in Fred: messages shouldn't be send from the player to the
68  * player.
69  * 
70  * 14    8/08/97 3:29p Duncan
71  * Fixed bug with strings exceeding their limits.
72  * 
73  * 13    8/05/97 5:12p Jasen
74  * Added advanced_stricmp() function to handle NULL pointers gracefully,
75  * and utilized it in message editor query update function.
76  * 
77  * 12    8/01/97 3:47p Hoffoss
78  * Fixed bug where message editor believes modifications occured when
79  * nothing actually changed.
80  * 
81  * 11    7/24/97 4:34p Hoffoss
82  * Fixed omission bug.
83  * 
84  * 10    7/16/97 6:30p Hoffoss
85  * Added icons to sexp trees, mainly because I think they will be required
86  * for drag n drop.
87  * 
88  * 9     7/14/97 9:55p Hoffoss
89  * Making changes to message editor system.
90  * 
91  * 8     7/10/97 2:32p Hoffoss
92  * Made message editor dialog box modeless.
93  * 
94  * 7     7/02/97 5:09p Hoffoss
95  * Added browse buttons to message editor.
96  * 
97  * 6     5/20/97 2:28p Hoffoss
98  * Added message box queries for close window operation on all modal
99  * dialog boxes.
100  * 
101  * 5     4/17/97 2:01p Hoffoss
102  * All dialog box window states are saved between sessions now.
103  * 
104  * 4     4/01/97 5:15p Hoffoss
105  * Fixed errors in max length checks, renaming a wing now renames the
106  * ships in the wing as well, as it should.
107  * 
108  * 3     3/11/97 2:19p Hoffoss
109  * New message structure support for Fred.
110  * 
111  * 2     2/17/97 5:28p Hoffoss
112  * Checked RCS headers, added them were missing, changing description to
113  * something better, etc where needed.
114  *
115  * $NoKeywords: $
116  */
117
118 #include "stdafx.h"
119 #include "fred.h"
120 #include "messageeditordlg.h"
121 #include "freddoc.h"
122 #include "management.h"
123 #include "sexp_tree.h"
124 #include "eventeditor.h"
125 #include "missionmessage.h"
126
127 #ifdef _DEBUG
128 #define new DEBUG_NEW
129 #undef THIS_FILE
130 static char THIS_FILE[] = __FILE__;
131 #endif
132
133 CMessageEditorDlg *Message_editor_dlg = NULL;
134
135 /////////////////////////////////////////////////////////////////////////////
136 // CMessageEditorDlg dialog
137
138 CMessageEditorDlg::CMessageEditorDlg(CWnd* pParent /*=NULL*/)
139         : CDialog(CMessageEditorDlg::IDD, pParent)
140 {
141         //{{AFX_DATA_INIT(CMessageEditorDlg)
142         m_avi_filename = _T("");
143         m_wave_filename = _T("");
144         m_message_text = _T("");
145         m_message_name = _T("");
146         m_cur_msg = -1;
147         m_priority = -1;
148         m_sender = -1;
149         m_persona = -1;
150         //}}AFX_DATA_INIT
151
152         m_tree.link_modified(&modified);
153         modified = 0;
154         m_event_num = -1;
155 }
156
157 void CMessageEditorDlg::DoDataExchange(CDataExchange* pDX)
158 {
159         CDialog::DoDataExchange(pDX);
160         //{{AFX_DATA_MAP(CMessageEditorDlg)
161         DDX_Control(pDX, IDC_TREE, m_tree);
162         DDX_CBString(pDX, IDC_AVI_FILENAME, m_avi_filename);
163         DDX_CBString(pDX, IDC_WAVE_FILENAME, m_wave_filename);
164         DDX_Text(pDX, IDC_MESSAGE_TEXT, m_message_text);
165         DDX_Text(pDX, IDC_NAME, m_message_name);
166         DDX_LBIndex(pDX, IDC_MESSAGE_LIST, m_cur_msg);
167         DDX_CBIndex(pDX, IDC_PRIORITY, m_priority);
168         DDX_CBIndex(pDX, IDC_SENDER, m_sender);
169         DDX_CBIndex(pDX, IDC_PERSONA_NAME, m_persona);
170         //}}AFX_DATA_MAP
171         DDV_MaxChars(pDX, m_message_name, NAME_LENGTH - 1);
172         DDV_MaxChars(pDX, m_message_text, MESSAGE_LENGTH - 1);
173         DDV_MaxChars(pDX, m_avi_filename, MAX_FILENAME_LEN - 1);
174         DDV_MaxChars(pDX, m_wave_filename, MAX_FILENAME_LEN - 1);
175 }
176
177 BEGIN_MESSAGE_MAP(CMessageEditorDlg, CDialog)
178         //{{AFX_MSG_MAP(CMessageEditorDlg)
179         ON_LBN_SELCHANGE(IDC_MESSAGE_LIST, OnSelchangeMessageList)
180         ON_EN_UPDATE(IDC_NAME, OnUpdateName)
181         ON_BN_CLICKED(IDC_DELETE, OnDelete)
182         ON_BN_CLICKED(IDC_NEW, OnNew)
183         ON_WM_CLOSE()
184         ON_BN_CLICKED(IDC_BROWSE_AVI, OnBrowseAvi)
185         ON_BN_CLICKED(IDC_BROWSE_WAVE, OnBrowseWave)
186         ON_NOTIFY(NM_RCLICK, IDC_TREE, OnRclickTree)
187         ON_NOTIFY(TVN_BEGINLABELEDIT, IDC_TREE, OnBeginlabeleditTree)
188         ON_NOTIFY(TVN_ENDLABELEDIT, IDC_TREE, OnEndlabeleditTree)
189         ON_BN_CLICKED(ID_OK, OnOk)
190         //}}AFX_MSG_MAP
191 END_MESSAGE_MAP()
192
193 /////////////////////////////////////////////////////////////////////////////
194 // CMessageEditorDlg message handlers
195
196 BOOL CMessageEditorDlg::OnInitDialog() 
197 {
198         int i;
199         CListBox *list;
200         CComboBox *box;
201
202         CDialog::OnInitDialog();
203         theApp.init_window(&Messages_wnd_data, this);
204         m_tree.setup();
205
206         ((CEdit *) GetDlgItem(IDC_NAME))->LimitText(NAME_LENGTH - 1);
207         ((CEdit *) GetDlgItem(IDC_MESSAGE_TEXT))->LimitText(MESSAGE_LENGTH - 1);
208         ((CComboBox *) GetDlgItem(IDC_AVI_FILENAME))->LimitText(MAX_FILENAME_LEN - 1);
209         ((CComboBox *) GetDlgItem(IDC_WAVE_FILENAME))->LimitText(MAX_FILENAME_LEN - 1);
210
211         list = (CListBox *) GetDlgItem(IDC_MESSAGE_LIST);
212         list->ResetContent();
213         for (i=0; i<Num_messages; i++) {
214                 //Assert(list->FindStringExact(-1, Messages[i].name) == CB_ERR);
215                 // mwa we should probably not include builtin messages into this list!
216                 list->AddString(Messages[i].name);
217         }
218
219         box = (CComboBox *) GetDlgItem(IDC_AVI_FILENAME);
220         for (i=0; i<Num_messages; i++)
221                 if (Messages[i].avi_info.name)
222                         if (box->FindStringExact(-1, Messages[i].avi_info.name) == CB_ERR)
223                                 box->AddString(Messages[i].avi_info.name);
224
225         box = (CComboBox *) GetDlgItem(IDC_WAVE_FILENAME);
226         for (i=0; i<Num_messages; i++)
227                 if (Messages[i].wave_info.name)
228                         if (box->FindStringExact(i, Messages[i].wave_info.name) == CB_ERR)
229                                 box->AddString(Messages[i].wave_info.name);
230
231         // add the persona names into the combo box
232         box = (CComboBox *)GetDlgItem(IDC_PERSONA_NAME);
233         box->ResetContent();
234         box->AddString("<None>");
235         for (i = 0; i < Num_personas; i++ )
236                 box->AddString( Personas[i].name );
237
238         box = (CComboBox *) GetDlgItem(IDC_SENDER);
239         for (i=0; i<MAX_SHIPS; i++)
240                 if ((Ships[i].objnum >= 0) && (Objects[Ships[i].objnum].type == OBJ_SHIP))
241                         box->AddString(Ships[i].ship_name);
242
243         for (i=0; i<MAX_WINGS; i++)
244                 if (Wings[i].wave_count)
245                         box->AddString(Wings[i].name);
246
247         box->AddString("<Any wingman>");
248
249         // MWA 4/7/98 -- removed any allied
250         //box->AddString("<Any allied>");
251
252         // set the first message to be the first non-builtin message (if it exists)
253         if ( Num_messages > Num_builtin_messages )
254                 m_cur_msg = Num_builtin_messages;
255         else if (Num_messages)
256                 m_cur_msg = 0;
257         else
258                 m_cur_msg = -1;
259
260         if (Num_messages >= MAX_MISSION_MESSAGES)
261                 GetDlgItem(IDC_NEW)->EnableWindow(FALSE);
262
263         update_cur_message();
264         return TRUE;
265 }
266
267 int CMessageEditorDlg::query_modified()
268 {
269         char *ptr, buf[MESSAGE_LENGTH];
270         int i;
271
272         UpdateData(TRUE);
273         if (modified)
274                 return 1;
275
276         if (m_cur_msg < 0)
277                 return 0;
278
279         ptr = (char *) (LPCTSTR) m_message_name;
280         for (i=0; i<Num_messages; i++)
281                 if ((i != m_cur_msg) && (!stricmp(ptr, Messages[i].name)))
282                         break;
283
284         if (i < Num_messages)
285                 if (stricmp(ptr, Messages[m_cur_msg].name))
286                         return 1;  // name is different and allowed to update
287
288         string_copy(buf, m_message_text, MESSAGE_LENGTH - 1);
289         if (stricmp(buf, Messages[m_cur_msg].message))
290                 return 1;
291
292         ptr = (char *) (LPCTSTR) m_avi_filename;
293         if (advanced_stricmp(ptr, Messages[m_cur_msg].avi_info.name))
294                 return 1;
295
296         ptr = (char *) (LPCTSTR) m_wave_filename;
297         if (advanced_stricmp(ptr, Messages[m_cur_msg].wave_info.name))
298                 return 1;
299
300         // check to see if persona changed.  use -1 since we stuck a "None" for persona
301         // at the beginning of the list.
302         if ( (m_persona - 1 ) != Messages[m_cur_msg].persona_index )
303                 return 1;
304
305         if (m_tree.query_false()) {
306                 if (m_event_num >= 0)
307                         return 1;
308
309         } else {
310                 if (m_event_num < 0)
311                         return 1;
312         }
313
314         return 0;
315 }
316
317 void CMessageEditorDlg::OnOK()
318 {
319 }
320
321 void CMessageEditorDlg::OnOk()
322 {
323         update(m_cur_msg);
324         theApp.record_window_data(&Messages_wnd_data, this);
325         delete Message_editor_dlg;
326         Message_editor_dlg = NULL;
327 }
328
329 void CMessageEditorDlg::OnCancel()
330 {
331         theApp.record_window_data(&Messages_wnd_data, this);
332         delete Message_editor_dlg;
333         Message_editor_dlg = NULL;
334 }
335
336 // load controls with structure data
337 void CMessageEditorDlg::update_cur_message()
338 {
339         int node, enable = TRUE, enable2 = TRUE;
340
341         if (m_cur_msg < 0)
342         {
343                 enable = enable2 = FALSE;
344                 m_message_name = _T("");
345                 m_message_text = _T("");
346                 m_avi_filename = _T("");
347                 m_wave_filename = _T("");
348                 m_tree.clear_tree();
349                 m_persona = 0;
350                 m_sender = m_priority = -1;
351
352         } else {
353                 m_message_name = Messages[m_cur_msg].name;
354                 m_message_text = Messages[m_cur_msg].message;
355                 if (Messages[m_cur_msg].avi_info.name)
356                         m_avi_filename = _T(Messages[m_cur_msg].avi_info.name);
357                 else
358                         m_avi_filename = _T("");
359
360                 if (Messages[m_cur_msg].wave_info.name)
361                         m_wave_filename = _T(Messages[m_cur_msg].wave_info.name);
362                 else
363                         m_wave_filename = _T("");
364
365                 // add persona id
366                 if ( Messages[m_cur_msg].persona_index != -1 )
367                         m_persona = Messages[m_cur_msg].persona_index + 1;              // add one for the "none" at the beginning of the list
368                 else
369                         m_persona = 0;
370
371                 m_event_num = find_event();
372                 if (m_event_num < 0) {
373                         node = -1;
374                         m_sender = m_priority = 0;
375
376                 } else
377                         node = CADR(Mission_events[m_event_num].formula);
378
379                 m_tree.load_tree(node, "false");
380         }
381
382         if (m_cur_msg < Num_builtin_messages)
383                 enable = FALSE;
384
385         GetDlgItem(IDC_NAME)->EnableWindow(enable);
386         GetDlgItem(IDC_MESSAGE_TEXT)->EnableWindow(enable);
387         GetDlgItem(IDC_AVI_FILENAME)->EnableWindow(enable);
388         GetDlgItem(IDC_WAVE_FILENAME)->EnableWindow(enable);
389         GetDlgItem(IDC_DELETE)->EnableWindow(enable);
390         GetDlgItem(IDC_TREE)->EnableWindow(enable2);
391         GetDlgItem(IDC_SENDER)->EnableWindow(enable2);
392         GetDlgItem(IDC_PRIORITY)->EnableWindow(enable2);
393         GetDlgItem(IDC_PERSONA_NAME)->EnableWindow(enable);
394         UpdateData(FALSE);
395 }
396
397 int CMessageEditorDlg::find_event()
398 {
399         char *str;
400         int i, formula, node;
401         CComboBox *box;
402
403         for (i=0; i<Num_mission_events; i++) {
404                 node = Mission_events[i].formula;
405                 if (find_operator(CTEXT(node)) == OP_WHEN) {
406                         node = CDR(node);
407                         formula = CAR(node);  // bool conditional
408                         if (CDR(CDR(node)) == -1) {  // only 1 action
409                                 node = CADR(node);
410                                 if ((find_operator(CTEXT(node)) == OP_SEND_MESSAGE) && !stricmp(CTEXT(CDR(CDR(CDR(node)))), m_message_name)) {
411                                         box = (CComboBox *) GetDlgItem(IDC_SENDER);
412                                         str = CTEXT(CDR(node));
413                                         m_sender = box->FindStringExact(-1, str);
414                                         if (m_sender == CB_ERR)
415                                                 m_sender = 0;
416
417                                         box = (CComboBox *) GetDlgItem(IDC_PRIORITY);
418                                         str = CTEXT(CDR(CDR(node)));
419                                         m_priority = box->FindStringExact(-1, str);
420                                         if (m_priority == CB_ERR)
421                                                 m_priority = 0;
422
423                                         return i;
424                                 }
425                         }
426                 }
427         }
428
429         m_sender = m_priority = 0;
430         return -1;
431 }
432
433 void CMessageEditorDlg::OnSelchangeMessageList() 
434 {
435         int old = m_cur_msg;
436         static flag = 0;
437
438         if (flag)
439                 return;
440
441         if (update(m_cur_msg)) {
442                 flag = 1;
443                 ((CListBox *) GetDlgItem(IDC_MESSAGE_LIST)) -> SetCurSel(old);
444                 m_cur_msg = old;
445                 flag = 0;
446                 return;
447         }
448
449         update_cur_message();
450 }
451
452 void CMessageEditorDlg::OnUpdateName() 
453 {
454 }
455
456 int CMessageEditorDlg::update(int num)
457 {
458         char *ptr, buf[4096];
459         int i, node, fnode;
460         CListBox *list;
461
462         UpdateData(TRUE);
463         if (num >= 0)
464         {
465                 ptr = (char *) (LPCTSTR) m_message_name;
466                 for (i=0; i<Num_messages; i++)
467                         if ((i != num) && (!stricmp(m_message_name, Messages[i].name)))
468                                 break;
469
470                 if (i == Num_messages) {  // update name if no conflicts, otherwise keep old name
471                         update_sexp_references(Messages[num].name, ptr, OPF_MESSAGE);
472                         string_copy(Messages[num].name, m_message_name, NAME_LENGTH - 1);
473
474                         list = (CListBox *) GetDlgItem(IDC_MESSAGE_LIST);
475                         list->DeleteString(num);
476                         list->InsertString(num, m_message_name);
477                 }
478
479                 string_copy(Messages[num].message, m_message_text, MESSAGE_LENGTH - 1);
480                 if (Messages[num].avi_info.name)
481                         free(Messages[num].avi_info.name);
482
483                 ptr = (char *) (LPCTSTR) m_avi_filename;
484                 if (!ptr || !strlen(ptr))
485                         Messages[num].avi_info.name = NULL;
486                 else
487                         Messages[num].avi_info.name = strdup(ptr);
488
489                 if (Messages[num].wave_info.name)
490                         free(Messages[num].wave_info.name);
491
492                 ptr = (char *) (LPCTSTR) m_wave_filename;
493                 if (!ptr || !strlen(ptr))
494                         Messages[num].wave_info.name = NULL;
495                 else
496                         Messages[num].wave_info.name = strdup(ptr);
497
498                 // update the persona to the message.  We subtract 1 for the "None" at the beginning of the combo
499                 // box list.
500                 Messages[num].persona_index = m_persona - 1;
501
502                 if (m_tree.query_false()) {
503                         if (m_event_num >= 0) {  // need to delete event
504                                 i = m_event_num;
505                                 free_sexp2(Mission_events[i].formula);
506                                 Assert(i < Num_mission_events);
507                                 while (i < Num_mission_events - 1) {
508                                         Mission_events[i] = Mission_events[i + 1];
509                                         i++;
510                                 }
511
512                                 Num_mission_events--;
513                                 m_event_num = -1;
514                         }
515
516                 } else {
517                         if (m_event_num >= 0)
518                                 free_sexp2(Mission_events[m_event_num].formula);
519                         
520                         else {
521                                 if (Num_mission_events == MAX_MISSION_EVENTS) {
522                                         MessageBox("You have reached the limit on mission events.\n"
523                                                 "Can't add an event to send this message.");
524
525                                         goto exit;
526                                 }
527
528                                 Assert(Num_mission_events < MAX_MISSION_EVENTS);
529                                 m_event_num = Num_mission_events++;
530                                 string_copy(Mission_events[m_event_num].name, m_message_name, NAME_LENGTH - 1);
531                                 Mission_events[m_event_num].repeat_count = 1;
532                                 Mission_events[m_event_num].interval = 1;
533                                 Mission_events[m_event_num].score = 0;
534                                 Mission_events[m_event_num].chain_delay = -1;
535                                 Mission_events[m_event_num].objective_text = NULL;
536                                 Mission_events[m_event_num].objective_key_text = NULL;
537                         }
538
539                         fnode = m_tree.save_tree();
540                         ptr = (char *) (LPCTSTR) m_message_name;
541                         node = alloc_sexp(ptr, SEXP_ATOM, SEXP_ATOM_STRING, -1, -1);
542                         ((CComboBox *) GetDlgItem(IDC_PRIORITY))->GetLBText(m_priority, buf);
543                         node = alloc_sexp(buf, SEXP_ATOM, SEXP_ATOM_STRING, -1, node);
544                         ((CComboBox *) GetDlgItem(IDC_SENDER))->GetLBText(m_sender, buf);
545                         node = alloc_sexp(buf, SEXP_ATOM, SEXP_ATOM_STRING, -1, node);
546                         node = alloc_sexp("send-message", SEXP_ATOM, SEXP_ATOM_OPERATOR, -1, node);
547                         node = alloc_sexp("", SEXP_LIST, SEXP_ATOM_LIST, node, -1);
548                         node = alloc_sexp("", SEXP_LIST, SEXP_ATOM_LIST, fnode, node);
549                         node = alloc_sexp("when", SEXP_ATOM, SEXP_ATOM_OPERATOR, -1, node);
550                         Mission_events[m_event_num].formula = node;
551                 }
552         }
553
554 exit:
555         if (query_modified())
556                 set_modified();
557
558         modified = 0;
559         return 0;
560 }
561
562 void CMessageEditorDlg::OnDelete() 
563 {
564         char buf[256];
565         int i;
566
567         Assert((m_cur_msg >= 0) && (m_cur_msg < Num_messages));
568         if (Messages[m_cur_msg].avi_info.name)
569                 free(Messages[m_cur_msg].avi_info.name);
570         if (Messages[m_cur_msg].wave_info.name)
571                 free(Messages[m_cur_msg].wave_info.name);
572
573         ((CListBox *) GetDlgItem(IDC_MESSAGE_LIST))->DeleteString(m_cur_msg);
574         sprintf(buf, "<%s>", Messages[m_cur_msg].name);
575         update_sexp_references(Messages[m_cur_msg].name, buf, OPF_MESSAGE);
576
577         for (i=m_cur_msg; i<Num_messages-1; i++)
578                 Messages[i] = Messages[i + 1];
579
580         Num_messages--;
581         if (m_cur_msg >= Num_messages)
582                 m_cur_msg = Num_messages - 1;
583
584         GetDlgItem(IDC_NEW)->EnableWindow(TRUE);
585         modified = 1;
586         update_cur_message();
587 }
588
589 void CMessageEditorDlg::OnNew() 
590 {
591         if (update(m_cur_msg))
592                 return;
593
594         Assert(Num_messages < MAX_MISSION_MESSAGES);
595         strcpy(Messages[Num_messages].name, "<new message>");
596         ((CListBox *) GetDlgItem(IDC_MESSAGE_LIST))->AddString("<new message>");
597
598         strcpy(Messages[Num_messages].message, "<put description here>");
599         Messages[Num_messages].avi_info.name = NULL;
600         Messages[Num_messages].wave_info.name = NULL;
601         Messages[Num_messages].persona_index = -1;
602         m_cur_msg = Num_messages++;
603         if (Num_messages >= MAX_MISSION_MESSAGES)
604                 GetDlgItem(IDC_NEW)->EnableWindow(FALSE);
605
606         modified = 1;
607         update_cur_message();
608 }
609
610 void CMessageEditorDlg::OnClose() 
611 {
612         int z;
613
614         modified = query_modified();
615         if (modified) {
616                 z = MessageBox("Do you want to keep your changes?", "Close", MB_ICONQUESTION | MB_YESNOCANCEL);
617                 if (z == IDCANCEL)
618                         return;
619
620                 if (z == IDYES) {
621                         OnOK();
622                         return;
623                 }
624         }
625         
626         theApp.record_window_data(&Messages_wnd_data, this);
627         delete Message_editor_dlg;
628         Message_editor_dlg = NULL;
629 }
630
631 void CMessageEditorDlg::OnBrowseAvi() 
632 {
633         CString name;   
634
635         UpdateData(TRUE);
636         CFileDialog dlg(TRUE, "ani", m_avi_filename, OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR,
637                 "Ani Files (*.ani)|*.ani|Avi Files (*.avi)|*.avi|Both (*.ani, *.avi)|*.ani;*.avi||");
638
639         if (dlg.DoModal() == IDOK)
640         {
641                 m_avi_filename = dlg.GetFileName();
642                 UpdateData(FALSE);
643                 modified = 1;
644         }
645 }
646
647 void CMessageEditorDlg::OnBrowseWave() 
648 {
649         CString name;   
650
651         UpdateData(TRUE);
652         CFileDialog dlg(TRUE, "wav", m_wave_filename, OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR,
653                 "Wave Files (*.wav)|*.wav||");
654
655         if (dlg.DoModal() == IDOK)
656         {
657                 m_wave_filename = dlg.GetFileName();
658                 UpdateData(FALSE);
659                 modified = 1;
660         }
661 }
662
663 void CMessageEditorDlg::OnRclickTree(NMHDR* pNMHDR, LRESULT* pResult) 
664 {
665         m_tree.right_clicked();
666         *pResult = 0;
667 }
668
669 void CMessageEditorDlg::OnBeginlabeleditTree(NMHDR* pNMHDR, LRESULT* pResult) 
670 {
671         TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;
672         CEdit *edit;
673
674         if (m_tree.edit_label(pTVDispInfo->item.hItem) == 1)    {
675                 *pResult = 0;
676                 modified = 1;
677                 edit = m_tree.GetEditControl();
678                 Assert(edit);
679                 edit->SetLimitText(NAME_LENGTH - 1);
680
681         } else
682                 *pResult = 1;
683 }
684
685 void CMessageEditorDlg::OnEndlabeleditTree(NMHDR* pNMHDR, LRESULT* pResult) 
686 {
687         TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;
688
689         *pResult = m_tree.end_label_edit(pTVDispInfo->item.hItem, pTVDispInfo->item.pszText);
690 }
691