]> icculus.org git repositories - taylor/freespace2.git/blob - src/fred2/fred.cpp
fix issue with looping audio streams
[taylor/freespace2.git] / src / fred2 / fred.cpp
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
6  * the source.
7  */
8
9 /*
10  * $Logfile: /Freespace2/code/Fred2/FRED.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * FRED.cpp : Defines the class behaviors for the application.
16  * Global editor dialog box classes are instantiated here, initializes the
17  * application (MFC level at least), processes the INI file.
18  *
19  * $Log$
20  * Revision 1.3  2002/06/09 04:41:16  relnev
21  * added copyright header
22  *
23  * Revision 1.2  2002/05/07 03:16:44  theoddone33
24  * The Great Newline Fix
25  *
26  * Revision 1.1.1.1  2002/05/03 03:28:08  root
27  * Initial import.
28  *
29  * 
30  * 6     5/19/99 4:07p Dave
31  * Moved versioning code into a nice isolated common place. Fixed up
32  * updating code on the pxo screen. Fixed several stub problems.
33  * 
34  * 5     3/26/99 4:49p Dave
35  * Made cruisers able to dock with stuff. Made docking points and paths
36  * visible in fred.
37  * 
38  * 4     3/20/99 5:09p Dave
39  * Fixed release build fred warnings and unhandled exception.
40  * 
41  * 3     10/29/98 10:41a Dave
42  * Change the way cfile initializes exe directory.
43  * 
44  * 2     10/07/98 6:28p Dave
45  * Initial checkin. Renamed all relevant stuff to be Fred2 instead of
46  * Fred. Globalized mission and campaign file extensions. Removed Silent
47  * Threat specific code.
48  * 
49  * 1     10/07/98 3:01p Dave
50  * 
51  * 1     10/07/98 3:00p Dave
52  * 
53  * 71    7/02/98 12:17p Hoffoss
54  * Load and save options 'anti-aliased gridlines' and 'double fine
55  * gridlines'.
56  * 
57  * 70    5/22/98 11:02a Allender
58  * Added error conditions on compile and new MAX_SHIPS limits for when
59  * FRED is defined when building
60  * 
61  * 69    5/22/98 1:06a Hoffoss
62  * Made Fred not use OLE.
63  * 
64  * 68    4/17/98 1:41p Allender
65  * took out function calls in NDEBUG mode
66  * 
67  * 67    3/25/98 4:14p Hoffoss
68  * Split ship editor up into ship editor and a misc dialog, which tracks
69  * flags and such.
70  * 
71  * 66    3/23/98 4:04p Hoffoss
72  * Fixed dialog window initialization so it looks better at startup (they
73  * don't flash on for a second).
74  * 
75  * 65    3/19/98 11:41a Hoffoss
76  * Fixed problems with rendering and reading of flying controls in Fred.
77  * 
78  * 64    3/19/98 11:11a Allender
79  * made Fred actually be able to move camera again -- Hoffos is going to
80  * fix the code right.
81  * 
82  * 63    3/18/98 3:10p Allender
83  * fixed update problems in OnIdle routine
84  * 
85  * 62    2/06/98 4:39p Hoffoss
86  * Added better checking for whether Fred is in the foreground or
87  * background.
88  * 
89  * 61    8/19/97 5:46p Hoffoss
90  * Changed font used in Fred, and added display to show current eye
91  * position.
92  * 
93  * 60    8/17/97 10:22p Hoffoss
94  * Fixed several bugs in Fred with Undo feature.  In the process, recoded
95  * a lot of CFile.cpp.
96  * 
97  * 59    8/14/97 2:32p Hoffoss
98  * fixed bug where controlling an object doesn't cause screen updates, and
99  * added a number of cool features to viewpoint/control object code.
100  * 
101  * 58    8/13/97 1:38p Hoffoss
102  * Added ability to update multiple times, which in needed in one case to
103  * brute force redraw so deleted ships actually do get removed from the
104  * display.
105  * 
106  * 57    8/12/97 6:32p Hoffoss
107  * Added code to allow hiding of arrival and departure cues in editors.
108  * 
109  * 56    8/10/97 4:52p Hoffoss
110  * Made Fred startup with main window having focus.
111  * 
112  * 55    8/06/97 7:55p Hoffoss
113  * Fixed bug with objects not seeming to be where they are drawn (due to
114  * new briefing clip render stuff).  This caused rendering problems,
115  * though.  So I fixed those next.
116  * 
117  * 54    8/05/97 1:29p Hoffoss
118  * show sexp help saved between sessions.
119  * 
120  * 53    8/01/97 3:10p Hoffoss
121  * Made Sexp help hidable.
122  * 
123  * 52    8/01/97 12:49p Hoffoss
124  * Changed recently used files total to 9 instead of 4.
125  * 
126  * 51    6/18/97 11:46a Hoffoss
127  * Fixed initial order object reference updating and added briefing dialog
128  * window tracking data.
129  * 
130  * 50    6/03/97 10:18a Allender
131  * make showCmd default to maximized since 0 will make the window hidden
132  * by default
133  * 
134  * 49    6/02/97 5:18p Hoffoss
135  * Fixed bug in error checker and improved startup code.
136  * 
137  * 48    6/02/97 11:52a Hoffoss
138  * Custom cursors displayed when over objects in different modes.
139  * 
140  * 47    5/12/97 12:27p John
141  * Restructured Graphics Library to add support for multiple renderers.
142  * 
143  * 46    5/09/97 9:45a Hoffoss
144  * Added OLE initialization. (needed for drag and drop functionality)
145  * 
146  * 45    5/06/97 10:34a Hoffoss
147  * Fixed bug where dialog boxes that change size (in the code) still
148  * retain their old size from the INI stored values.  They are resized now
149  * automatically.
150  * 
151  * 44    5/05/97 9:41a Hoffoss
152  * Campaign editor begun.
153  * 
154  * 43    5/02/97 8:39a Allender
155  * turn of heap allocation debuging
156  * 
157  * 42    4/29/97 1:58p Hoffoss
158  * Added some debugging to Fred to try and track down sexp corruption
159  * causes.
160  * 
161  * 41    4/28/97 3:43p Hoffoss
162  * Show_waypoints defaults to on for Fred, and is saved as a preference
163  * now.
164  * 
165  * 40    4/17/97 2:01p Hoffoss
166  * All dialog box window states are saved between sessions now.
167  * 
168  * 39    4/03/97 11:35a Hoffoss
169  * Fixed bugs: viewpoint didn't reset, initial orders not updated when
170  * referenced ship is renamed or deleted.
171  * 
172  * 38    4/01/97 11:43p Mike
173  * Resolve link errors due to addition of SystemVars.cpp.
174  * 
175  * 37    3/26/97 12:44p Hoffoss
176  * Took out the debugging 3d compass on/off toggling I put in to test
177  * rerendering with.
178  * 
179  * 36    3/20/97 3:55p Hoffoss
180  * Major changes to how dialog boxes initialize (load) and update (save)
181  * their internal data.  This should simplify things and create less
182  * problems.
183  * 
184  * 35    3/13/97 12:08p Hoffoss
185  * Waypoint path editor finished (apparently I didn't get around to
186  * completing it before).
187  * 
188  * 34    3/12/97 12:39p Hoffoss
189  * Fixed bugs in wing object management functions, several small additions
190  * and rearrangements.
191  * 
192  * 33    3/06/97 3:35p Hoffoss
193  * Added Show_outline stuff, moved show options to the view menu, fixed a
194  * bug in message dialog editor.
195  * 
196  * 32    2/28/97 11:31a Hoffoss
197  * Implemented modeless dialog saving and restoring, and changed some
198  * variables names.
199  * 
200  * 31    2/27/97 5:54p Hoffoss
201  * Implemented support for saving and restoring window positions.
202  * 
203  * 30    2/25/97 6:10p Hoffoss
204  * Fixed bug with modeless dialog box errors on update.
205  * 
206  * 29    2/24/97 12:50p Hoffoss
207  * First attempt at non-continuous redrawing.
208  * 
209  * 28    2/17/97 5:28p Hoffoss
210  * Checked RCS headers, added them were missing, changing description to
211  * something better, etc where needed.
212  * 
213  * 27    2/12/97 12:25p Hoffoss
214  * Expanded on global error checker, added initial orders conflict
215  * checking and warning, added waypoint editor dialog and code.
216  * 
217  * 26    1/30/97 2:24p Hoffoss
218  * Added remaining mission file structures and implemented load/save of
219  * them.
220  *
221  * $NoKeywords: $
222  */
223
224 #include "stdafx.h"
225 #include "fred.h"
226
227 #include "mainfrm.h"
228 #include "freddoc.h"
229 #include "fredview.h"
230 #include "fredrender.h"
231 #include "management.h"
232
233 #include "2d.h"
234 #include "key.h"
235 #include "object.h"
236 #include "editor.h"
237 #include "campaigntreewnd.h"
238 #include "campaigntreeview.h"
239 #include "campaigneditordlg.h"
240
241 #ifdef NDEBUG
242 #ifndef FRED
243 #error macro FRED is not defined when trying to build release Fred.  Please define FRED macro in build settings in all Fred projects
244 #endif
245 #endif
246
247 #ifdef _DEBUG
248 #define new DEBUG_NEW
249 #undef THIS_FILE
250 static char THIS_FILE[] = __FILE__;
251 #endif
252
253 int     Fred_running = 1;
254 int     User_interface = HOFFOSS_INTERFACE;
255 int     FrameCount = 0;
256 int     Fred_active = 1;
257 int     Update_window = 1;
258 HCURSOR h_cursor_move, h_cursor_rotate;
259
260 CWnd *Prev_window;
261 CShipEditorDlg  Ship_editor_dialog;
262 wing_editor             Wing_editor_dialog;
263 waypoint_path_dlg       Waypoint_editor_dialog;
264 bg_bitmap_dlg   *Bg_bitmap_dialog = NULL;
265 briefing_editor_dlg     *Briefing_dialog = NULL;
266
267 window_data Main_wnd_data;
268 window_data Ship_wnd_data;
269 window_data Wing_wnd_data;
270 window_data Object_wnd_data;
271 window_data Mission_goals_wnd_data;
272 window_data Messages_wnd_data;
273 window_data Player_wnd_data;
274 window_data Events_wnd_data;
275 window_data Bg_wnd_data;
276 window_data Briefing_wnd_data;
277 window_data Reinforcement_wnd_data;
278 window_data Waypoint_wnd_data;
279 window_data Starfield_wnd_data;
280 window_data Asteroid_wnd_data;
281 window_data Mission_notes_wnd_data;
282
283 /////////////////////////////////////////////////////////////////////////////
284 // CFREDApp
285
286 BEGIN_MESSAGE_MAP(CFREDApp, CWinApp)
287         //{{AFX_MSG_MAP(CFREDApp)
288         ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
289                 // NOTE - the ClassWizard will add and remove mapping macros here.
290                 //    DO NOT EDIT what you see in these blocks of generated code!
291         //}}AFX_MSG_MAP
292         // Standard file based document commands
293         ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
294         ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
295         // Standard print setup command
296         ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup)
297 END_MESSAGE_MAP()
298
299 /////////////////////////////////////////////////////////////////////////////
300 // CFREDApp construction
301
302 CFREDApp::CFREDApp()
303 {
304         app_init = 0;
305
306         #ifndef NDEBUG
307         outwnd_init();
308         #endif
309         // TODO: add construction code here,
310         // Place all significant initialization in InitInstance
311 }
312
313 /////////////////////////////////////////////////////////////////////////////
314 // The one and only CFREDApp object
315
316 CFREDApp theApp;
317
318 /////////////////////////////////////////////////////////////////////////////
319 // CFREDApp initialization
320 char *c;
321 char *tok = "whee";
322 BOOL CFREDApp::InitInstance()
323 {       
324         // disable the debug memory stuff
325         _CrtSetDbgFlag(~(_CRTDBG_ALLOC_MEM_DF) & _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG));
326
327         // Standard initialization
328         // If you are not using these features and wish to reduce the size
329         //  of your final executable, you should remove from the following
330         //  the specific initialization routines you do not need.
331
332 #ifdef _AFXDLL
333         Enable3dControls();                     // Call this when using MFC in a shared DLL
334 #else
335         Enable3dControlsStatic();       // Call this when linking to MFC statically
336 #endif
337
338         LoadStdProfileSettings(9);  // Load standard INI file options (including MRU)
339         User_interface = GetProfileInt("Preferences", "User interface", User_interface);
340         Show_stars = GetProfileInt("Preferences", "Show stars", Show_stars);
341         Show_grid_positions = GetProfileInt("Preferences", "Show grid positions", Show_grid_positions);
342         Show_coordinates = GetProfileInt("Preferences", "Show coordinates", Show_coordinates);
343         Show_compass = GetProfileInt("Preferences", "Show compass", Show_compass);
344         Show_ship_models = GetProfileInt("Preferences", "Show ship models", Show_ship_models);
345         Show_ship_info = GetProfileInt("Preferences", "Show ship info", Show_ship_info);
346         Show_outlines = GetProfileInt("Preferences", "Show outlines", Show_outlines);
347         Show_waypoints = GetProfileInt("Preferences", "Show waypoints", Show_waypoints);
348         Show_sexp_help = GetProfileInt("Preferences", "Show sexp help", Show_sexp_help);
349         physics_speed = GetProfileInt("Preferences", "Physics speed", physics_speed);
350         physics_rot = GetProfileInt("Preferences", "Physics rotation", physics_rot);
351         Hide_ship_cues = GetProfileInt("Preferences", "Hide ship cues", Hide_ship_cues);
352         Hide_wing_cues = GetProfileInt("Preferences", "Hide wing cues", Hide_wing_cues);
353         Autosave_disabled = GetProfileInt("Preferences", "Autosave disabled", Autosave_disabled);
354         double_fine_gridlines = GetProfileInt("Preferences", "Double fine gridlines", double_fine_gridlines);
355         Aa_gridlines = GetProfileInt("Preferences", "Anti aliased gridlines", Aa_gridlines);
356         Show_dock_points = GetProfileInt("Preferences", "Show dock points", Show_dock_points);
357         Show_paths_fred = GetProfileInt("Preferences", "Show paths", Show_paths_fred);
358         read_window("Main window", &Main_wnd_data);
359         read_window("Ship window", &Ship_wnd_data);
360         read_window("Wing window", &Wing_wnd_data);
361         read_window("Waypoint window", &Waypoint_wnd_data);
362         read_window("Object window", &Object_wnd_data);
363         read_window("Mission goals window", &Mission_goals_wnd_data);
364         read_window("Messages window", &Messages_wnd_data);
365         read_window("Player window", &Player_wnd_data);
366         read_window("Events window", &Events_wnd_data);
367         read_window("Bg window", &Bg_wnd_data);
368         read_window("Briefing window", &Briefing_wnd_data);
369         read_window("Reinforcement window", &Reinforcement_wnd_data);
370         read_window("Starfield window", &Starfield_wnd_data);
371         read_window("Asteroid window", &Asteroid_wnd_data);
372         read_window("Mission notes window", &Mission_notes_wnd_data);
373         write_ini_file(1);
374
375         // Register the application's document templates.  Document templates
376         //  serve as the connection between documents, frame windows and views.
377
378         CSingleDocTemplate* pDocTemplate;
379         pDocTemplate = new CSingleDocTemplate(
380                 IDR_MAINFRAME,
381                 RUNTIME_CLASS(CFREDDoc),
382                 RUNTIME_CLASS(CMainFrame),       // main SDI frame window
383                 RUNTIME_CLASS(CFREDView));
384         AddDocTemplate(pDocTemplate);
385
386         // Enable DDE Execute open
387         EnableShellOpen();
388         RegisterShellFileTypes(TRUE);   
389
390         // setup the fred exe directory so CFILE can init properly
391         /*
392         c = GetCommandLine();
393         SDL_assert(c != NULL);
394         if(c == NULL){
395                 return FALSE;
396         } 
397         tok = strtok(c, " \n");
398         SDL_assert(tok != NULL);
399         if(tok == NULL){
400                 return FALSE;           
401         }
402         // Fred_exe_dir = strdup(c);            
403         strcpy(Fred_exe_dir, tok);
404         */
405         strcpy(Fred_exe_dir, __argv[0]);
406
407         // Parse command line for standard shell commands, DDE, file open
408         CCommandLineInfo cmdInfo;
409         ParseCommandLine(cmdInfo);      
410
411         m_nCmdShow = Main_wnd_data.p.showCmd;
412         OnFileNew();
413
414         // Enable drag/drop open
415         m_pMainWnd->DragAcceptFiles();
416
417         h_cursor_move = LoadCursor(IDC_CURSOR1);
418         h_cursor_rotate = LoadCursor(IDC_CURSOR2);
419         return TRUE;
420 }
421
422 /////////////////////////////////////////////////////////////////////////////
423 // CAboutDlg dialog used for App About
424
425 class CAboutDlg : public CDialog
426 {
427 public:
428         CAboutDlg();
429
430 // Dialog Data
431         //{{AFX_DATA(CAboutDlg)
432         enum { IDD = IDD_ABOUTBOX };
433         //}}AFX_DATA
434
435         // ClassWizard generated virtual function overrides
436         //{{AFX_VIRTUAL(CAboutDlg)
437         protected:
438         virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
439         //}}AFX_VIRTUAL
440
441 // Implementation
442 protected:
443         //{{AFX_MSG(CAboutDlg)
444         //}}AFX_MSG
445         DECLARE_MESSAGE_MAP()
446 };
447
448 CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
449 {
450         //{{AFX_DATA_INIT(CAboutDlg)
451         //}}AFX_DATA_INIT
452 }
453
454 void CAboutDlg::DoDataExchange(CDataExchange* pDX)
455 {
456         CDialog::DoDataExchange(pDX);
457         //{{AFX_DATA_MAP(CAboutDlg)
458         //}}AFX_DATA_MAP
459 }
460
461 BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
462         //{{AFX_MSG_MAP(CAboutDlg)
463         //}}AFX_MSG_MAP
464 END_MESSAGE_MAP()
465
466 // App command to run the dialog
467 void CFREDApp::OnAppAbout()
468 {
469         CAboutDlg aboutDlg;
470         aboutDlg.DoModal();
471 }
472
473 /////////////////////////////////////////////////////////////////////////////
474 // CFREDApp commands
475
476 char *edit_mode_text[] = {
477         "Ships",
478         "Waypoints",
479 };
480 /*      "Grid",
481         "Wing",
482         "Object Relative"
483 };
484 */
485
486 char *control_mode_text[] = {
487         "Camera",
488         "Object"
489 };
490
491 void show_control_mode(void)
492 {
493         CString str;
494
495         CMainFrame* pFrame = (CMainFrame*) AfxGetApp()->m_pMainWnd;
496         CStatusBar* pStatus = &pFrame->m_wndStatusBar;
497         //CStatusBarCtrl pStatusBarCtrl;
498
499         if (pStatus) {
500 //              pStatus->GetStatusBarCtrl().SetParts(NUM_STATUS_PARTS, parts);
501
502                 if (Marked)
503                         str.Format("Marked: %d", Marked);
504                 else
505                         str = _T("");
506                 pStatus->SetPaneText(1, str);
507
508                 if (viewpoint)
509                         str.Format("Viewpoint: %s", object_name(view_obj));
510                 else
511                         str.Format("Viewpoint: Camera");
512
513                 pStatus->SetPaneText(2, str);
514                 
515                 if (FREDDoc_ptr->IsModified())
516                         pStatus->SetPaneText(3, "MODIFIED");
517                 else
518                         pStatus->SetPaneText(3, "");
519
520                 str.Format("Units = %.1f Meters", The_grid->square_size);
521                 pStatus->SetPaneText(4, str);
522
523 //              pStatus->SetPaneText(4, "abcdefg");
524 //              pStatus->SetPaneText(4, "1234567890!");
525         }
526         
527 }
528
529 #define MAX_PENDING_MESSAGES    16
530
531 typedef struct {
532         int     frame_to_process, hwnd, id, wparam, lparam;
533 } pending_message;
534
535 pending_message Pending_messages[MAX_PENDING_MESSAGES];
536
537 //      Process messages that needed to wait until a frame had gone by.
538 void process_pending_messages(void)
539 {
540         int     i;
541
542         for (i=0; i<MAX_PENDING_MESSAGES; i++)
543                 if (Pending_messages[i].frame_to_process != -1)
544                         if (Pending_messages[i].frame_to_process <= FrameCount) {
545                                 pending_message *pmp = &Pending_messages[i];
546                                 PostMessage((HWND) pmp->hwnd, pmp->id, pmp->wparam, pmp->lparam);
547                                 Pending_messages[i].frame_to_process = -1;
548                         }
549 }
550
551 //      Add a message to be processed to a buffer.
552 //      Wait skip_count frames before processing.
553 void add_pending_message(HWND hwnd, int id, int wparam, int lparam, int skip_count)
554 {
555         int     i;
556
557         for (i=0; i<MAX_PENDING_MESSAGES; i++)
558                 if (Pending_messages[i].frame_to_process == -1) {
559                         Pending_messages[i].hwnd = (int) hwnd;
560                         Pending_messages[i].id = id;
561                         Pending_messages[i].wparam = wparam;
562                         Pending_messages[i].lparam = lparam;
563                         Pending_messages[i].frame_to_process = FrameCount + skip_count;
564                 }
565 }
566
567 void init_pending_messages(void)
568 {
569         int     i;
570
571         for (i=0; i<MAX_PENDING_MESSAGES; i++)
572                 Pending_messages[i].frame_to_process = -1;
573 }
574
575 // void win32_blit(HDC hSrcDC, HPALETTE hPalette, int x, int y, int w, int h )
576 #if 0
577 void win32_blit(void *xx, void *yy, int x, int y, int w, int h )
578 {
579         HPALETTE hOldPalette = NULL;
580         HDC hdc = GetDC(hwndApp);
581
582         if ( !hdc )     return;
583         if ( !fAppActive ) return;
584
585         if (hPalette)   {
586                 hOldPalette = SelectPalette(hdc, hPalette, FALSE);
587                 RealizePalette( hdc );
588         }
589
590         BitBlt(hdc, 0, 0, w, h, hSrcDC, x, y, SRCCOPY);
591         
592         if ( hOldPalette )      
593                 SelectPalette(hdc, hOldPalette, FALSE);
594
595         ReleaseDC( hwndApp, hdc );
596 }
597 #endif
598
599 void draw_render_window(CDC* pDC)
600 {
601         int w, h;
602
603         w = gr_screen.clip_width;
604         h = gr_screen.clip_height;
605         gr_screen.clip_width = gr_screen.max_w;
606         gr_screen.clip_height = gr_screen.max_h;
607         gr_flip_window((uint) pDC->m_hDC, 0, 0, gr_screen.max_w, gr_screen.max_h);
608         gr_screen.clip_width = w;
609         gr_screen.clip_height = h;
610 }
611
612 BOOL CFREDApp::OnIdle(LONG lCount)
613 {
614         int adjust = 0;
615         CWnd *top, *wnd;
616
617         if (!Show_sexp_help)
618                 adjust = -SEXP_HELP_BOX_SIZE;
619
620         if (!app_init) {
621                 app_init = 1;
622                 theApp.init_window(&Ship_wnd_data, &Ship_editor_dialog, adjust, 1);
623                 theApp.init_window(&Wing_wnd_data, &Wing_editor_dialog, adjust, 1);
624                 theApp.init_window(&Waypoint_wnd_data, &Waypoint_editor_dialog, 0, 1);
625                 init_window(&Main_wnd_data, Fred_main_wnd);
626                 Fred_main_wnd->SetWindowPos(&CWnd::wndTop, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
627
628                 Ship_editor_dialog.calc_cue_height();
629                 Wing_editor_dialog.calc_cue_height();
630         }
631
632         CWinApp::OnIdle(lCount);
633         internal_integrity_check();
634         if (Update_ship) {
635                 Ship_editor_dialog.initialize_data(1);
636                 Update_ship = 0;
637         }
638
639         if (Update_wing) {
640                 Wing_editor_dialog.initialize_data(1);
641                 Update_wing = 0;
642         }
643
644         Prev_window = CFREDView::GetActiveWindow();
645
646         // Find the root window of the active window
647         wnd = top = Prev_window;
648         while (wnd) {
649                 top = wnd;
650                 wnd = wnd->GetParent();
651         }
652
653         // See if the active window is a child of Fred
654         if (Prev_window)
655                 Fred_active = ( (top == Fred_main_wnd) || (top == Campaign_wnd) );
656         else
657                 Fred_active = 0;
658
659         if (!Fred_active)
660                 return FALSE;  // if fred isn't active, don't waste any time with it.
661
662         game_do_frame();  // do stuff that needs doing, whether we render or not.
663         show_control_mode();
664
665         if (!Update_window)
666                 return FALSE;
667
668         render_frame(); // "do the rendering!"  Renders image to offscreen buffer
669
670         CFREDView* pFV = CFREDView::GetView();
671         CDC* pDC = pFV->GetDC();
672
673         // gr_surface_flip();
674
675         // if you hit the next SDL_assert, find Hoffoss or Allender.  If neither here, then comment it out.
676         SDL_assert( Update_window >= 0 );
677         if (Update_window) {
678                 draw_render_window(pDC);  // this actually copies the offscreen buffer to the screen
679                 Update_window--;
680         }
681
682         process_pending_messages();
683         pFV->ReleaseDC(pDC);
684
685         FrameCount++;
686         return TRUE;
687 }
688
689 void update_map_window()
690 {
691         if (Fred_active) {
692                 Update_window++;  // on idle will handle the drawing already.
693                 return;
694         }
695
696         if (!Fred_main_wnd)
697                 return;
698
699         CFREDView* pFV = CFREDView::GetView();
700         if (!pFV)
701                 return;
702
703         render_frame(); // "do the rendering!"
704
705         CDC* pDC = pFV->GetDC();
706         SDL_assert(pDC);
707
708         draw_render_window(pDC);
709         if ( Update_window > 0 )
710                 Update_window--;
711
712         show_control_mode();
713         process_pending_messages();
714         pFV->ReleaseDC(pDC);
715
716         FrameCount++;
717 }
718
719 void CFREDApp::write_ini_file(int degree)
720 {
721         WriteProfileInt("Preferences", "User interface", User_interface);
722         WriteProfileInt("Preferences", "Show stars", Show_stars);
723         WriteProfileInt("Preferences", "Show grid positions", Show_grid_positions);
724         WriteProfileInt("Preferences", "Show coordinates", Show_coordinates);
725         WriteProfileInt("Preferences", "Show compass", Show_compass);
726         WriteProfileInt("Preferences", "Show ship models", Show_ship_models);
727         WriteProfileInt("Preferences", "Show ship info", Show_ship_info);
728         WriteProfileInt("Preferences", "Show outlines", Show_outlines);
729         WriteProfileInt("Preferences", "Physics speed", physics_speed);
730         WriteProfileInt("Preferences", "Physics rotation", physics_rot);
731         WriteProfileInt("Preferences", "Show waypoints", Show_waypoints);
732         WriteProfileInt("Preferences", "Show sexp help", Show_sexp_help);
733         WriteProfileInt("Preferences", "Hide ship cues", Hide_ship_cues);
734         WriteProfileInt("Preferences", "Hide wing cues", Hide_wing_cues);
735         WriteProfileInt("Preferences", "Autosave disabled", Autosave_disabled);
736         WriteProfileInt("Preferences", "Double fine gridlines", double_fine_gridlines);
737         WriteProfileInt("Preferences", "Anti aliased gridlines", Aa_gridlines);
738         WriteProfileInt("Preferences", "Show dock points",      Show_dock_points);
739         WriteProfileInt("Preferences", "Show paths",    Show_paths_fred);
740
741         if (!degree) {
742                 record_window_data(&Waypoint_wnd_data, &Waypoint_editor_dialog);
743                 record_window_data(&Wing_wnd_data, &Wing_editor_dialog);
744                 record_window_data(&Ship_wnd_data, &Ship_editor_dialog);
745                 record_window_data(&Main_wnd_data, Fred_main_wnd);
746
747                 write_window("Main window", &Main_wnd_data);
748                 write_window("Ship window", &Ship_wnd_data);
749                 write_window("Wing window", &Wing_wnd_data);
750                 write_window("Waypoint window", &Waypoint_wnd_data);
751                 write_window("Object window", &Object_wnd_data);
752                 write_window("Mission goals window", &Mission_goals_wnd_data);
753                 write_window("Messages window", &Messages_wnd_data);
754                 write_window("Player window", &Player_wnd_data);
755                 write_window("Events window", &Events_wnd_data);
756                 write_window("Bg window", &Bg_wnd_data);
757                 write_window("Briefing window", &Briefing_wnd_data);
758                 write_window("Reinforcement window", &Reinforcement_wnd_data);
759                 write_window("Starfield window", &Starfield_wnd_data);
760                 write_window("Asteroid window", &Asteroid_wnd_data);
761                 write_window("Mission notes window", &Mission_notes_wnd_data);
762         }
763 }
764
765 void CFREDApp::write_window(char *name, window_data *wndd)
766 {
767         WriteProfileInt(name, "valid", wndd->valid);
768         WriteProfileInt(name, "length", wndd->p.length);
769         WriteProfileInt(name, "flags", wndd->p.flags);
770         WriteProfileInt(name, "showCmd", wndd->p.showCmd);
771         WriteProfileInt(name, "ptMinPosition.x", wndd->p.ptMinPosition.x);
772         WriteProfileInt(name, "ptMinPosition.y", wndd->p.ptMinPosition.y);
773         WriteProfileInt(name, "ptMaxPosition.x", wndd->p.ptMaxPosition.x);
774         WriteProfileInt(name, "ptMaxPosition.y", wndd->p.ptMaxPosition.y);
775         WriteProfileInt(name, "rcNormalPosition.left", wndd->p.rcNormalPosition.left);
776         WriteProfileInt(name, "rcNormalPosition.top", wndd->p.rcNormalPosition.top);
777         WriteProfileInt(name, "rcNormalPosition.right", wndd->p.rcNormalPosition.right);
778         WriteProfileInt(name, "rcNormalPosition.bottom", wndd->p.rcNormalPosition.bottom);
779         WriteProfileInt(name, "Visible", wndd->visible);
780 }
781
782 void CFREDApp::read_window(char *name, window_data *wndd)
783 {
784         wndd->processed = 0;
785         wndd->valid = GetProfileInt(name, "valid", FALSE);
786         wndd->p.length = GetProfileInt(name, "length", 0);
787         wndd->p.flags = GetProfileInt(name, "flags", 0);
788         wndd->p.showCmd = GetProfileInt(name, "showCmd", SW_SHOWMAXIMIZED);
789         wndd->p.ptMinPosition.x = GetProfileInt(name, "ptMinPosition.x", 0);
790         wndd->p.ptMinPosition.y = GetProfileInt(name, "ptMinPosition.y", 0);
791         wndd->p.ptMaxPosition.x = GetProfileInt(name, "ptMaxPosition.x", 0);
792         wndd->p.ptMaxPosition.y = GetProfileInt(name, "ptMaxPosition.y", 0);
793         wndd->p.rcNormalPosition.left = GetProfileInt(name, "rcNormalPosition.left", 0);
794         wndd->p.rcNormalPosition.top = GetProfileInt(name, "rcNormalPosition.top", 0);
795         wndd->p.rcNormalPosition.right = GetProfileInt(name, "rcNormalPosition.right", 0);
796         wndd->p.rcNormalPosition.bottom = GetProfileInt(name, "rcNormalPosition.bottom", 0);
797         wndd->visible = GetProfileInt(name, "Visible", 1);
798 }
799
800 int CFREDApp::init_window(window_data *wndd, CWnd *wnd, int adjust, int pre)
801 {
802         int width, height;
803         WINDOWPLACEMENT p;
804
805         if (pre && !wndd->visible)
806                 return -1;
807
808         if (wndd->processed)
809                 return -2;
810
811         SDL_assert(wnd->GetSafeHwnd());
812         wnd->GetWindowPlacement(&p);
813         width = p.rcNormalPosition.right - p.rcNormalPosition.left;
814         height = p.rcNormalPosition.bottom - p.rcNormalPosition.top + adjust;
815         wndd->p.rcNormalPosition.right = wndd->p.rcNormalPosition.left + width;
816         wndd->p.rcNormalPosition.bottom = wndd->p.rcNormalPosition.top + height;
817
818         if (wndd->valid) {
819                 wnd->SetWindowPlacement(&wndd->p);
820 //              if (!wndd->visible)
821 //                      wnd->ShowWindow(SW_SHOW);
822 //              else
823 //                      wnd->ShowWindow(SW_HIDE);
824         }
825
826         record_window_data(wndd, wnd);
827         wndd->processed = 1;
828         return 0;
829 }
830
831 void CFREDApp::record_window_data(window_data *wndd, CWnd *wnd)
832 {
833         wnd->GetWindowPlacement(&wndd->p);
834         wndd->visible = wnd->IsWindowVisible();
835         wndd->valid = TRUE;
836 }
837