]> icculus.org git repositories - taylor/freespace2.git/blob - src/fred2/mainfrm.cpp
Initial revision
[taylor/freespace2.git] / src / fred2 / mainfrm.cpp
1 /*
2  * $Logfile: /Freespace2/code/Fred2/MainFrm.cpp $
3  * $Revision$
4  * $Date$
5  * $Author$
6  *
7  * MainFrm.cpp : implementation of the CMainFrame class
8  * The main frame class of a document/view architechure, which we hate but must
9  * deal with, due to Microsoft limiting our freedom and forcing us to use whether
10  * we want to or not.  The main frame is basically the container window that other
11  * view windows are within.  In Fred, our view window is always maximized inside
12  * the main frame window, so you can't tell the difference between the two.  A few
13  * old MFC events are handled here because the people working on the code before
14  * me (Hoffoss) decided to put it here.  I've been putting it all in FredView.
15  *
16  * $Log$
17  * Revision 1.1  2002/05/03 03:28:08  root
18  * Initial revision
19  *
20  * 
21  * 8     10/13/99 2:55p Jefff
22  * fixed unnumbered XSTRs
23  * 
24  * 7     10/13/99 9:22a Daveb
25  * Fixed Fred jumpnode placing bug. Fixed 1024 glide tiled texture problem
26  * related to movies. Fixed launcher spawning from PXO screen.
27  * 
28  * 6     9/14/99 11:07p Andsager
29  * Improve freddoc error message.  Fix Frerd2 about box for "2" part of
30  * Fred2
31  * 
32  * 5     9/08/99 12:07a Andsager
33  * Add browser based help to Fred
34  * 
35  * 4     9/01/99 10:15a Dave
36  * 
37  * 3     11/19/98 8:36a Dave
38  * Removed ST reordering of ships in Fred.
39  * 
40  * 2     10/07/98 6:28p Dave
41  * Initial checkin. Renamed all relevant stuff to be Fred2 instead of
42  * Fred. Globalized mission and campaign file extensions. Removed Silent
43  * Threat specific code.
44  * 
45  * 1     10/07/98 3:02p Dave
46  * 
47  * 1     10/07/98 3:00p Dave
48  * 
49  * 31    9/16/98 6:54p Dave
50  * Upped  max sexpression nodes to 1800 (from 1600). Changed FRED to sort
51  * the ship list box. Added code so that tracker stats are not stored with
52  * only 1 player.
53  * 
54  * 30    3/09/98 10:56a Hoffoss
55  * Added jump node objects to Fred.
56  * 
57  * 29    2/20/98 12:56p Adam
58  * Made ship class box even wider.
59  * 
60  * 28    2/20/98 12:07p Hoffoss
61  * Made ship type combo box on toolbar wider.
62  * 
63  * 27    9/30/97 2:11p Hoffoss
64  * Removed player start item from toolbar combo box.
65  * 
66  * 26    8/21/97 5:39p Hoffoss
67  * Fixed warning when building optimized.  Was MFC code I copied, which
68  * says something about MFC I guess.
69  * 
70  * 25    8/17/97 10:22p Hoffoss
71  * Fixed several bugs in Fred with Undo feature.  In the process, recoded
72  * a lot of CFile.cpp.
73  * 
74  * 24    8/14/97 2:32p Hoffoss
75  * fixed bug where controlling an object doesn't cause screen updates, and
76  * added a number of cool features to viewpoint/control object code.
77  * 
78  * 23    7/21/97 3:57p Hoffoss
79  * Removed group combo box from toolbar, since I don't think I'll ever get
80  * it working right.
81  * 
82  * 22    6/26/97 12:39p Mike
83  * Add ship_type to ship_info and ships.tbl.
84  * 
85  * 21    6/09/97 4:57p Hoffoss
86  * Added autosave and undo to Fred.
87  * 
88  * 20    5/05/97 1:35p Hoffoss
89  * View window is now refocused when a new ship type selection is made.
90  * 
91  * 19    5/01/97 10:54a Hoffoss
92  * Removed obsolete files/classes from Fred project, and any reference to
93  * them.
94  * 
95  * 18    4/17/97 2:01p Hoffoss
96  * All dialog box window states are saved between sessions now.
97  * 
98  * 17    4/03/97 11:35a Hoffoss
99  * Fixed bugs: viewpoint didn't reset, initial orders not updated when
100  * referenced ship is renamed or deleted.
101  * 
102  * 16    3/10/97 4:58p Hoffoss
103  * Added waypoint and start types to drop down toolbar combo box and fixed
104  * context menu new ship type selection to also work.
105  * 
106  * 15    3/10/97 12:54p Hoffoss
107  * Added drop down combo box to toolbar and fixed compiling errors Mark
108  * (maybe Mike?) introduced to code.
109  * 
110  * 14    2/28/97 11:31a Hoffoss
111  * Implemented modeless dialog saving and restoring, and changed some
112  * variables names.
113  * 
114  * 13    2/27/97 5:54p Hoffoss
115  * Implemented support for saving and restoring window positions.
116  * 
117  * 12    2/17/97 5:28p Hoffoss
118  * Checked RCS headers, added them were missing, changing description to
119  * something better, etc where needed.
120  *
121  * $NoKeywords: $
122  */
123
124 #include "stdafx.h"
125 #include "fred.h"
126
127 #include "mainfrm.h"
128
129 #include "freddoc.h"
130 #include "fredview.h"
131
132 #include "messageeditordlg.h"
133 #include "shipclasseditordlg.h"
134 #include "missionnotesdlg.h"
135 #include "grid.h"
136 #include "dialog1.h"
137
138 #ifdef _DEBUG
139 #define new DEBUG_NEW
140 #undef THIS_FILE
141 static char THIS_FILE[] = __FILE__;
142 #endif
143
144 /////////////////////////////////////////////////////////////////////////////
145 // CMainFrame
146
147 IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)
148
149 BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
150         ON_MESSAGE(WM_MENU_POPUP_EDIT, OnMenuPopupTest)
151         ON_CBN_SELCHANGE(ID_NEW_SHIP_TYPE, OnNewShipTypeChange)
152
153         //{{AFX_MSG_MAP(CMainFrame)
154         ON_WM_CREATE()
155         ON_COMMAND(ID_EDITORS_AI_CLASSES, OnEditorsAiClasses)
156         ON_COMMAND(ID_EDITORS_GOALS, OnEditorsGoals)
157         ON_COMMAND(ID_EDITORS_ART, OnEditorsArt)
158         ON_COMMAND(ID_EDITORS_MUSIC, OnEditorsMusic)
159         ON_COMMAND(ID_EDITORS_SHIP_CLASSES, OnEditorsShipClasses)
160         ON_COMMAND(ID_EDITORS_SOUND, OnEditorsSound)
161         ON_COMMAND(ID_EDITORS_TERRAIN, OnEditorsTerrain)
162         ON_COMMAND(ID_FILE_MISSIONNOTES, OnFileMissionnotes)
163         ON_WM_LBUTTONUP()
164         ON_WM_DESTROY()
165         ON_COMMAND(ID_VIEW_STATUS_BAR, OnViewStatusBar)
166         ON_UPDATE_COMMAND_UI(ID_VIEW_STATUS_BAR, OnUpdateViewStatusBar)
167         ON_UPDATE_COMMAND_UI(ID_INDICATOR_LEFT, OnUpdateLeft)
168         ON_UPDATE_COMMAND_UI(ID_INDICATOR_RIGHT, OnUpdateRight)
169         ON_COMMAND(ID_MIKE_GRIDCONTROL, OnMikeGridcontrol)
170         ON_COMMAND(IDR_MENU_POPUP_TOGGLE1, OnMenuPopupToggle1)
171         ON_UPDATE_COMMAND_UI(IDR_MENU_POPUP_TOGGLE1, OnUpdateMenuPopupToggle1)
172         ON_WM_RBUTTONDOWN()
173         ON_COMMAND(ID_HELP_INPUT_INTERFACE, OnHelpInputInterface)
174         ON_WM_CLOSE()
175         ON_WM_INITMENU()
176         ON_COMMAND(ID_HELP_FINDER, OnFredHelp)
177         ON_COMMAND(ID_HELP, OnFredHelp)
178         //ON_COMMAND(ID_CONTEXT_HELP, OnFredHelp)
179         //ON_COMMAND(ID_DEFAULT_HELP, OnFredHelp)
180         //}}AFX_MSG_MAP
181         // Global help commands
182 END_MESSAGE_MAP()
183
184 #define FRED_HELP_URL "\\data\\freddocs\\index.html"
185
186 static UINT indicators[] =
187 {
188         ID_SEPARATOR,           // status line indicator
189         ID_SEPARATOR,
190         ID_SEPARATOR,
191         ID_INDICATOR_MODIFIED,
192         ID_SEPARATOR,
193 //      ID_INDICATOR_LEFT,
194 //      ID_INDICATOR_RIGHT,
195 //      ID_INDICATOR_CAPS,
196 //      ID_INDICATOR_NUM,
197 //      ID_INDICATOR_SCRL,
198 };
199
200 CMainFrame      *Fred_main_wnd;
201 color_combo_box m_new_ship_type_combo_box;
202
203 /////////////////////////////////////////////////////////////////////////////
204 // CMainFrame construction/destruction
205
206 CMainFrame::CMainFrame()
207 {
208 }
209
210 CMainFrame::~CMainFrame()
211 {
212 }
213
214 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
215 {
216         int z;
217         CRect rect;
218
219         if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
220                 return -1;
221         
222         if (!m_wndToolBar.Create(this) ||
223                 !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
224         {
225                 TRACE0("Failed to create toolbar\n");
226                 return -1;      // fail to create
227         }
228
229         // Create the combo box
230         z = m_wndToolBar.CommandToIndex(ID_NEW_SHIP_TYPE);
231         Assert(z != -1);
232         m_wndToolBar.SetButtonInfo(z, ID_NEW_SHIP_TYPE, TBBS_SEPARATOR, 230);
233
234         // Design guide advises 12 pixel gap between combos and buttons
235 //      m_wndToolBar.SetButtonInfo(1, ID_SEPARATOR, TBBS_SEPARATOR, 12);
236         m_wndToolBar.GetItemRect(z, &rect);
237         rect.top = 3;
238         rect.bottom = rect.top + 550;
239         if (!m_new_ship_type_combo_box.Create(CBS_DROPDOWNLIST | WS_VISIBLE | WS_VSCROLL | CBS_HASSTRINGS | LBS_OWNERDRAWFIXED,
240                 rect, &m_wndToolBar, ID_NEW_SHIP_TYPE))
241         {
242                 TRACE0("Failed to create new ship type combo-box\n");
243                 return FALSE;
244         }
245
246 /*      if (!m_wndStatusBar.Create(this) ||
247                 !m_wndStatusBar.SetIndicators(indicators,
248                   sizeof(indicators)/sizeof(UINT)))
249         {
250                 TRACE0("Failed to create status bar\n");
251                 return -1;      // fail to create
252         }
253 */
254
255 /*      if (!m_wndStatusBar.Create(this,
256                 WS_CHILD | WS_VISIBLE | CBRS_BOTTOM, ID_MY_STATUS_BAR) ||
257                 !m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT)))*/
258
259         if (!m_wndStatusBar.Create(this) ||
260                 !m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT)))
261         {
262                 TRACE0("Failed to create status bar\n");
263                 return -1;
264
265         } else {
266                 m_wndStatusBar.SetPaneInfo(0, 0, SBPS_STRETCH, 0);
267                 m_wndStatusBar.SetPaneInfo(1, 0, SBPS_NORMAL, 80);
268                 m_wndStatusBar.SetPaneInfo(2, 0, SBPS_NORMAL, 180);
269 //              m_wndStatusBar.SetPaneInfo(3, 0, SBPS_NORMAL, 100);
270                 m_wndStatusBar.SetPaneInfo(4, 0, SBPS_NORMAL, 130);
271         }
272
273         // TODO: Remove this if you don't want tool tips or a resizeable toolbar
274         m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() |
275                 CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
276
277         // TODO: Delete these three lines if you don't want the toolbar to
278         //  be dockable
279         m_wndToolBar.EnableDocking(CBRS_ALIGN_TOP | CBRS_ALIGN_BOTTOM);
280         EnableDocking(CBRS_ALIGN_ANY);
281         DockControlBar(&m_wndToolBar);
282
283         Fred_main_wnd = this;
284         Ship_editor_dialog.Create();
285         Wing_editor_dialog.Create();
286         Waypoint_editor_dialog.Create();
287         init_tools();
288         LoadBarState("Tools state");
289         return 0;
290 }
291
292 BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
293 {
294         // TODO: Modify the Window class or styles here by modifying
295         //  the CREATESTRUCT cs
296
297         return CFrameWnd::PreCreateWindow(cs);
298 }
299
300 /////////////////////////////////////////////////////////////////////////////
301 // CMainFrame diagnostics
302
303 #ifdef _DEBUG
304 void CMainFrame::AssertValid() const
305 {
306         CFrameWnd::AssertValid();
307 }
308
309 void CMainFrame::Dump(CDumpContext& dc) const
310 {
311         CFrameWnd::Dump(dc);
312 }
313
314 #endif //_DEBUG
315
316 //void CMainFrame::OnEditorsShips() 
317 //{
318 //      CShipEditorDlg  dlg;
319 //
320 //      dlg.DoModal();
321 //              
322 //}
323
324 void CMainFrame::OnEditorsAiClasses() 
325 {
326 }
327
328 void CMainFrame::OnEditorsGoals() 
329 {
330 }
331
332 void CMainFrame::OnEditorsArt() 
333 {
334 }
335
336 void CMainFrame::OnEditorsMusic() 
337 {
338 }
339
340 void CMainFrame::OnEditorsShipClasses() 
341 {
342 }
343
344 void CMainFrame::OnEditorsSound() 
345 {
346 }
347
348 void CMainFrame::OnEditorsTerrain() 
349 {
350 }
351
352 void CMainFrame::OnFileMissionnotes() 
353 {
354         CMissionNotesDlg        dlg;
355
356         dlg.DoModal();
357 }
358
359 // I have been unable to get this message event to occur.
360 void CMainFrame::OnLButtonUp(UINT nFlags, CPoint point) 
361 {
362         CFrameWnd::OnLButtonUp(nFlags, point);
363 }
364
365 // This event is invoked when you click on the black X in the upper right corner
366 // or when you do File/Exit.
367 void CMainFrame::OnDestroy() 
368 {
369         Fred_main_wnd = NULL;   
370         CFrameWnd::OnDestroy();
371 }
372
373 void CMainFrame::OnViewStatusBar() 
374 {
375         m_wndStatusBar.ShowWindow((m_wndStatusBar.GetStyle() & WS_VISIBLE) == 0);
376         RecalcLayout();
377 }
378
379 void CMainFrame::OnUpdateViewStatusBar(CCmdUI* pCmdUI) 
380 {
381         pCmdUI->SetCheck((m_wndStatusBar.GetStyle() & WS_VISIBLE) != 0);
382 }
383
384 void CMainFrame::OnUpdateLeft(CCmdUI* pCmdUI)
385 {
386         pCmdUI->Enable(::GetKeyState(VK_LBUTTON) < 0);
387 }
388
389 void CMainFrame::OnUpdateRight(CCmdUI* pCmdUI)
390 {
391         pCmdUI->Enable(::GetKeyState(VK_RBUTTON) < 0);
392 }
393
394 void CMainFrame::OnMikeGridcontrol() 
395 {
396         CGrid   dlg;
397
398         dlg.DoModal();
399 }
400
401 int     Toggle1_var = 0;
402
403 void CMainFrame::OnMenuPopupToggle1() 
404 {
405         if (Toggle1_var == 0)
406                 Toggle1_var = 1;
407         else
408                 Toggle1_var = 0;
409         
410 }
411
412 void CMainFrame::OnUpdateMenuPopupToggle1(CCmdUI* pCmdUI) 
413 {
414         pCmdUI->SetCheck(Toggle1_var);
415 }
416
417 LONG CMainFrame::OnMenuPopupTest(UINT wParam, LONG lParam)
418 {
419         CMenu   menu;
420         CPoint  point;
421
422         point = * ((CPoint*) lParam);
423         
424         ClientToScreen(&point);
425
426         menu.LoadMenu(IDR_MENU1);
427         menu.GetSubMenu(0)->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this);
428
429         return 0L;
430 }
431
432 CPoint  Global_point2;
433
434 void CMainFrame::OnRButtonDown(UINT nFlags, CPoint point) 
435 {
436         Global_point2 = point;
437
438         PostMessage(WM_MENU_POPUP_TEST, nFlags, (int) &Global_point2);
439         CFrameWnd::OnRButtonDown(nFlags, point);
440 }
441
442 void CMainFrame::OnHelpInputInterface() 
443 {
444         dialog1 dlg;
445
446         dlg.DoModal();
447 }
448
449 void CMainFrame::OnClose()
450 {
451         theApp.write_ini_file();
452         SaveBarState("Tools state");
453         CFrameWnd::OnClose();
454 }
455
456 void CMainFrame::init_tools()
457 {
458         static int count = 0;
459         int i;
460         //int highest_terran_index;
461         //char ship_name[256];
462         //int ship_index;
463
464         Assert(count < 2);
465
466         // add 
467         if (count++) {
468                 for (i=0; i<Num_ship_types; i++){
469                         // don't add the pirate ship
470                         if(Ship_info[i].flags & SIF_NO_FRED){
471                                 m_new_ship_type_combo_box.AddString("");
472                                 continue;
473                         }
474
475                         m_new_ship_type_combo_box.AddString(Ship_info[i].name);
476                 }
477
478 //              m_new_ship_type_combo_box.AddString("Player Start");            
479                 m_new_ship_type_combo_box.AddString("Jump Node");
480                 m_new_ship_type_combo_box.AddString("Waypoint");                
481
482                 /*
483                 // now we want to sort special ships (mission disk) ----------------------
484                 highest_terran_index = 0;
485                 memset(ship_name, 0, 256);
486                 while(m_new_ship_type_combo_box.GetLBText(highest_terran_index, ship_name) != CB_ERR){
487                         ship_index = ship_info_lookup(ship_name);
488                         if((ship_index < 0) || (ship_index >= Num_ship_types) || (Ship_info[ship_index].species != SPECIES_TERRAN)){
489                                 break;
490                         }
491                         highest_terran_index++;
492                 }               
493                 */
494         }       
495 }
496
497 void CMainFrame::OnNewShipTypeChange()
498 {
499         if (Fred_view_wnd)
500                 Fred_view_wnd->SetFocus();
501 }
502
503 void color_combo_box::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
504 {
505         int m_cyText = 24, z;
506         CString strText;
507         char ship_name[256];
508
509         // You must override DrawItem and MeasureItem for LBS_OWNERDRAWVARIABLE
510         ASSERT((GetStyle() & (LBS_OWNERDRAWFIXED | CBS_HASSTRINGS)) ==
511                 (LBS_OWNERDRAWFIXED | CBS_HASSTRINGS));
512
513         CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
514
515         // I think we need to do a lookup by ship name here     
516         if(lpDrawItemStruct->itemID >= (uint)Num_ship_types){
517                 z = lpDrawItemStruct->itemID;
518         } else {                
519                 memset(ship_name, 0, 256);
520                 GetLBText(lpDrawItemStruct->itemID, ship_name);
521                 z = ship_info_lookup(ship_name);
522         }
523
524         if ((z >= 0) && (lpDrawItemStruct->itemAction & (ODA_DRAWENTIRE | ODA_SELECT)))
525         {
526                 int cyItem = GetItemHeight(z);
527                 BOOL fDisabled = !IsWindowEnabled();
528
529                 COLORREF newTextColor = RGB(0x80, 0x80, 0x80);  // light gray
530                 if (!fDisabled) {
531                         if (z >= Num_ship_types)
532                                 newTextColor = RGB(0, 0, 0);
533                         else
534                                 switch (Ship_info[z].species)   {
535                                         case SPECIES_TERRAN:            newTextColor = RGB(0, 0, 192);  break;
536                                         case SPECIES_VASUDAN:   newTextColor = RGB(0, 128, 0);  break;
537                                         case SPECIES_SHIVAN:            newTextColor = RGB(192, 0, 0);  break;
538                                         case SPECIES_NONE:              newTextColor = RGB(224, 128, 0);        break;
539                                 }
540                 }
541
542                 COLORREF oldTextColor = pDC->SetTextColor(newTextColor);
543                 COLORREF newBkColor = GetSysColor(COLOR_WINDOW);
544                 COLORREF oldBkColor = pDC->SetBkColor(newBkColor);
545
546                 if (newTextColor == newBkColor)
547                         newTextColor = RGB(0xC0, 0xC0, 0xC0);   // dark gray
548
549                 if (!fDisabled && ((lpDrawItemStruct->itemState & ODS_SELECTED) != 0))
550                 {
551                         pDC->SetTextColor(GetSysColor(COLOR_HIGHLIGHTTEXT));
552                         pDC->SetBkColor(GetSysColor(COLOR_HIGHLIGHT));
553                 }
554
555                 if (m_cyText == 0)
556                         VERIFY(cyItem >= CalcMinimumItemHeight());
557
558                 if (z == Id_select_type_jump_node)
559                         strText = _T("Jump Node");
560                 else if (z == Id_select_type_start)
561                         strText = _T("Player Start");
562                 else if (z == Id_select_type_waypoint)
563                         strText = _T("Waypoint");
564                 else
565                         strText = _T(Ship_info[z].name);
566 //              GetLBText(lpDrawItemStruct->itemID, strText);
567
568                 pDC->ExtTextOut(lpDrawItemStruct->rcItem.left,
569                         lpDrawItemStruct->rcItem.top + max(0, (cyItem - m_cyText) / 2),
570                         ETO_OPAQUE, &(lpDrawItemStruct->rcItem), strText, strText.GetLength(), NULL);
571
572                 pDC->SetTextColor(oldTextColor);
573                 pDC->SetBkColor(oldBkColor);
574         }
575
576         if ((lpDrawItemStruct->itemAction & ODA_FOCUS) != 0)
577                 pDC->DrawFocusRect(&(lpDrawItemStruct->rcItem));
578 }
579
580 int color_combo_box::CalcMinimumItemHeight()
581 {
582         int nResult = 1;
583
584         if ((GetStyle() & (LBS_HASSTRINGS | LBS_OWNERDRAWFIXED)) ==
585                 (LBS_HASSTRINGS | LBS_OWNERDRAWFIXED))
586         {
587                 CClientDC dc(this);
588                 CFont* pOldFont = dc.SelectObject(GetFont());
589                 TEXTMETRIC tm;
590                 VERIFY (dc.GetTextMetrics ( &tm ));
591                 dc.SelectObject(pOldFont);
592
593                 nResult = tm.tmHeight;
594         }
595
596         return nResult;
597 }
598
599 void color_combo_box::MeasureItem(LPMEASUREITEMSTRUCT)
600 {
601         // You must override DrawItem and MeasureItem for LBS_OWNERDRAWVARIABLE
602         ASSERT((GetStyle() & (LBS_OWNERDRAWFIXED | CBS_HASSTRINGS)) ==
603                 (LBS_OWNERDRAWFIXED | CBS_HASSTRINGS));
604 }
605
606 int color_combo_box::SetCurSelNEW(int model_index)
607 {       
608         if((model_index < 0) || (model_index >= Num_ship_types)){
609                 return SetCurSel(model_index);
610         }       
611
612         // lookup the ship name
613         return FindString(0, Ship_info[model_index].name);
614 }
615
616 int color_combo_box::GetCurSelNEW()
617 {
618         int cur_sel;
619         int ship_info;
620         char ship_name[256];
621         char *hmmm = ship_name;
622
623         // see if we have a special item (>= Num_ship_types)
624         cur_sel = GetCurSel();
625         if(cur_sel >= Num_ship_types){
626                 return cur_sel;
627         }
628
629         // otherwise lookup the ship by name
630         memset(ship_name, 0, 256);
631         if(GetLBText(cur_sel, hmmm) == CB_ERR){
632                 return CB_ERR;
633         }
634         ship_info = ship_info_lookup(ship_name);
635         if((ship_info < 0) || (ship_info >= Num_ship_types)){
636                 return CB_ERR;
637         }
638         return ship_info;
639 }
640
641 void CMainFrame::OnInitMenu(CMenu* pMenu) 
642 {
643         CString str;
644
645         if (Undo_available && !FREDDoc_ptr->undo_desc[1].IsEmpty())
646                 str = "Undo " + FREDDoc_ptr->undo_desc[1] + "\tCtrl+Z";
647         else
648                 str = "Undo\tCtrl+Z";
649
650         if (pMenu->GetMenuState(ID_EDIT_UNDO, MF_BYCOMMAND) != -1)
651                 pMenu->ModifyMenu(ID_EDIT_UNDO, MF_BYCOMMAND, ID_EDIT_UNDO, str);
652
653         CFrameWnd::OnInitMenu(pMenu);
654 }
655
656
657 void url_launch(char *url)
658 {
659         int r;
660
661         r = (int) ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOW);
662         if (r < 32) {
663                 char *txt = NULL;
664
665                 switch (r) {
666                         case 0: txt = XSTR("The operating system is out of memory or resources.", 1107); break;
667                         case ERROR_BAD_FORMAT: txt = XSTR("The .EXE file is invalid (non-Win32 .EXE or error in .EXE image).", 1108); break;
668                         case SE_ERR_ACCESSDENIED: txt = XSTR("The operating system denied access to the specified file. ", 1109); break;
669                         case SE_ERR_ASSOCINCOMPLETE: txt = XSTR("The filename association is incomplete or invalid.\r\n(You need to have a default Internet browser installed)", 1110); break;
670                         case SE_ERR_DDEBUSY: txt = XSTR("The DDE transaction could not be completed because other DDE transactions were being processed.", 1111); break;
671                         case SE_ERR_DDEFAIL: txt = XSTR("The DDE transaction failed.", 1112); break;
672                         case SE_ERR_DDETIMEOUT: txt = XSTR("The DDE transaction could not be completed because the request timed out.", 1113); break;
673                         case SE_ERR_DLLNOTFOUND: txt = XSTR("The specified dynamic-link library was not found.", 1114); break;
674                         case SE_ERR_OOM: txt = XSTR("There was not enough memory to complete the operation.", 1115); break;
675                         case SE_ERR_SHARE: txt = XSTR("A sharing violation occurred.", 1116); break;
676
677                         // No browser installed message
678                         case SE_ERR_NOASSOC:
679                         case ERROR_FILE_NOT_FOUND:
680                         case ERROR_PATH_NOT_FOUND: txt =        XSTR("\r\nUnable to locate Fred Help file: \\data\\freddocs\\index.html\r\n", 1479); break;
681
682                         default: txt = XSTR("Unknown error occurred.", 1118); break;
683                 }
684                 AfxMessageBox(txt, MB_OK | MB_ICONERROR);
685         }
686 }
687
688
689 void CMainFrame::OnFredHelp()
690 {
691         char buffer[_MAX_PATH];
692
693         // get exe path
694         strcpy(buffer, Fred_exe_dir);
695
696         // strip exe name
697         char *last_slash = strrchr(buffer, '\\');
698         if ( last_slash == NULL) {
699                 return;
700         } else {
701                 *last_slash = 0;
702         }
703
704         // add rest of path
705         strcat(buffer, FRED_HELP_URL);
706
707         // shell_open url
708         url_launch(buffer);
709 }
710