]> git.mxchange.org Git - flightgear.git/blob - src/GUI/gui.cxx
e3386dae90bd026931b99ba34219924b5959a486
[flightgear.git] / src / GUI / gui.cxx
1 /**************************************************************************
2  * gui.cxx
3  *
4  * Written 1998 by Durk Talsma, started Juni, 1998.  For the flight gear
5  * project.
6  *
7  * Additional mouse supported added by David Megginson, 1999.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as
11  * published by the Free Software Foundation; either version 2 of the
12  * License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  *
23  * $Id$
24  **************************************************************************/
25
26
27 #ifdef HAVE_CONFIG_H
28 #  include <config.h>
29 #endif
30
31 #include <Include/compiler.h>
32
33 #ifdef FG_MATH_EXCEPTION_CLASH
34 #  include <math.h>
35 #endif
36
37 #ifdef HAVE_WINDOWS_H
38 #  include <windows.h>
39 #endif
40
41 #include <GL/glut.h>
42 #include <XGL/xgl.h>
43
44 #if defined(FX) && defined(XMESA)
45 #  include <GL/xmesa.h>
46 #endif
47
48 #include STL_STRING
49
50 #include <stdlib.h>
51 #include <string.h>
52
53 #include <Include/general.hxx>
54 #include <Debug/logstream.hxx>
55 #include <Aircraft/aircraft.hxx>
56 #include <Airports/simple.hxx>
57 #include <Cockpit/panel.hxx>
58 #include <FDM/flight.hxx>
59 #include <Main/options.hxx>
60 #include <Main/fg_init.hxx>
61 #include <Main/views.hxx>
62 #include <Misc/fgpath.hxx>
63 #include <Network/network.h>
64 #include <Screen/screen-dump.hxx>
65 #include <Time/fg_time.hxx>
66
67 #ifdef WIN32
68 #  include <Screen/win32-printer.h>
69 #endif
70
71 #include "gui.h"
72
73 FG_USING_STD(string);
74
75 #ifndef FG_HAVE_NATIVE_SGI_COMPILERS
76 FG_USING_STD(cout);
77 #endif
78
79 // hack, should come from an include someplace
80 extern void fgInitVisuals( void );
81 extern void fgReshape( int width, int height );
82 extern void fgRenderFrame( void );
83
84 puFont guiFnt = 0;
85 fntTexFont *guiFntHandle = 0;
86
87 static puMenuBar    *mainMenuBar = 0;
88 //static puButton     *hideMenuButton = 0;
89
90 static puDialogBox  *dialogBox = 0;
91 static puFrame      *dialogFrame = 0;
92 static puText       *dialogBoxMessage = 0;
93 static puOneShot    *dialogBoxOkButton = 0;
94
95
96 static puDialogBox  *YNdialogBox = 0;
97 static puFrame      *YNdialogFrame = 0;
98 static puText       *YNdialogBoxMessage = 0;
99 static puOneShot    *YNdialogBoxOkButton = 0;
100 static puOneShot    *YNdialogBoxNoButton = 0;
101
102 static char msg_OK[]     = "OK";
103 static char msg_NO[]     = "NO";
104 static char msg_YES[]    = "YES";
105 static char msg_CANCEL[] = "Cancel";
106 static char msg_RESET[]  = "Reset";
107
108 char *gui_msg_OK;     // "OK"
109 char *gui_msg_NO;     // "NO"
110 char *gui_msg_YES;    // "YES"
111 char *gui_msg_CANCEL; // "CANCEL"
112 char *gui_msg_RESET;  // "RESET"
113
114 static char global_dialog_string[256];
115
116 extern void NewAltitude( puObject *cb );
117 extern void NewHeading( puObject *cb );
118 extern void fgAPAdjust( puObject * );
119 extern void fgLatLonFormatToggle( puObject *);
120 extern void NewTgtAirport( puObject *cb );
121
122 /* --------------------------------------------------------------------
123 Mouse stuff
124 ---------------------------------------------------------------------*/
125
126 static int _mX = 0;
127 static int _mY = 0;
128 static int _savedX = 0;
129 static int _savedY = 0;
130 static int last_buttons = 0 ;
131 static int mouse_active = 0;
132 static int menu_on = 0;
133
134 /* --------------------------------------------------------------------
135 Support for mouse as control yoke (david@megginson.com)
136
137 - right button toggles between pointer and yoke
138 - horizontal drag with no buttons moves ailerons
139 - vertical drag with no buttons moves elevators
140 - horizontal drag with left button moves brakes (left=on)
141 - vertical drag with left button moves throttle (up=more)
142 - horizontal drag with middle button moves rudder
143 - vertical drag with middle button moves trim
144
145 For the *_sensitivity variables, a lower number means more sensitive.
146
147 TODO: figure out how to keep pointer from leaving window in yoke mode.
148 TODO: add thresholds and null zones
149 TODO: sensitivity should be configurable at user option.
150 TODO: allow differential braking (this will be useful if FlightGear
151       ever supports tail-draggers like the DC-3)
152 ---------------------------------------------------------------------*/
153
154 typedef enum {
155     MOUSE_POINTER,
156     MOUSE_YOKE,
157     MOUSE_VIEW
158 } MouseMode;
159
160 MouseMode mouse_mode = MOUSE_POINTER;
161 static float aileron_sensitivity = 500.0;
162 static float elevator_sensitivity = 500.0;
163 static float brake_sensitivity = 250.0;
164 static float throttle_sensitivity = 250.0;
165 static float rudder_sensitivity = 500.0;
166 static float trim_sensitivity = 1000.0;
167
168 void guiMotionFunc ( int x, int y )
169 {
170     if (mouse_mode == MOUSE_POINTER) {
171       puMouse ( x, y ) ;
172       glutPostRedisplay () ;
173     } else {
174       int ww = current_view.get_winWidth();
175       int wh = current_view.get_winHeight();
176
177                                 // Mouse as yoke
178       if (mouse_mode == MOUSE_YOKE) {
179         if (last_buttons & (1 << GLUT_LEFT_BUTTON)) {
180           float brake_offset = (_mX - x) / brake_sensitivity;
181           float throttle_offset = (_mY - y) / throttle_sensitivity;
182           controls.move_brake(FGControls::ALL_WHEELS, brake_offset);
183           controls.move_throttle(FGControls::ALL_ENGINES, throttle_offset);
184         } else if (last_buttons & (1 << GLUT_MIDDLE_BUTTON)) {
185           float rudder_offset = (x - _mX) / rudder_sensitivity;
186           float trim_offset = (_mY - y) / trim_sensitivity;
187           controls.move_rudder(rudder_offset);
188           controls.move_elevator_trim(trim_offset);
189         } else {
190           float aileron_offset = (x - _mX) / aileron_sensitivity;
191           float elevator_offset = (_mY - y) / elevator_sensitivity;
192           controls.move_aileron(aileron_offset);
193           controls.move_elevator(elevator_offset);
194         }
195
196                                 // Mouse as view
197       } else {
198         FGView * v = &current_view;
199         double offset = v->get_goal_view_offset();
200         double full = FG_PI * 2.0;
201         offset += (_mX - x) / 500.0;
202         while (offset < 0) {
203           offset += full;
204         }
205         while (offset > full) {
206           offset -= full;
207         }
208         v->set_view_offset(offset);
209         v->set_goal_view_offset(offset);
210       }
211
212                                 // Keep the mouse in the window.
213       if (x < 5 || x > ww-5 || y < 5 || y > wh-5) {
214         _mX = x = ww / 2;
215         _mY = y = wh / 2;
216         glutWarpPointer(x, y);
217       }
218     }
219
220                                 // Record the new mouse position.
221     _mX = x;
222     _mY = y;
223 }
224
225 void guiMouseFunc(int button, int updown, int x, int y)
226 {
227                                 // Was the left button pressed?
228     if (updown == GLUT_DOWN && button == GLUT_LEFT_BUTTON) {
229       switch (mouse_mode) {
230       case MOUSE_POINTER:
231         break;
232       case MOUSE_YOKE:
233         break;
234       case MOUSE_VIEW:
235         current_view.set_view_offset( 0.00 );
236         current_view.set_goal_view_offset( 0.00 );
237         break;
238       }
239
240                                 // Or was it the right button?
241     } else if (updown == GLUT_DOWN && button == GLUT_RIGHT_BUTTON) {
242       switch (mouse_mode) {
243       case MOUSE_POINTER:
244         mouse_mode = MOUSE_YOKE;
245         _savedX = x;
246         _savedY = y;
247         glutSetCursor(GLUT_CURSOR_NONE);
248         FG_LOG( FG_INPUT, FG_INFO, "Mouse in yoke mode" );
249         break;
250       case MOUSE_YOKE:
251         mouse_mode = MOUSE_VIEW;
252         FG_LOG( FG_INPUT, FG_INFO, "Mouse in view mode" );
253         break;
254       case MOUSE_VIEW:
255         mouse_mode = MOUSE_POINTER;
256         _mX = x = _savedX;
257         _mY = y = _savedY;
258         glutWarpPointer(x, y);
259         glutSetCursor(GLUT_CURSOR_INHERIT);
260         FG_LOG( FG_INPUT, FG_INFO, "Mouse in pointer mode" );
261         break;
262       }     
263     }
264
265                                 // Register the new position (if it
266                                 // hasn't been registered already).
267     _mX = x;
268     _mY = y;
269
270                                 // Note which button is pressed.
271     if ( updown == GLUT_DOWN ) {
272         last_buttons |=  ( 1 << button ) ;
273     } else {
274         last_buttons &= ~( 1 << button ) ;
275     }
276
277                                 // If we're in pointer mode, let PUI
278                                 // know what's going on.
279     if (mouse_mode == MOUSE_POINTER) {
280         puMouse (button, updown, x,y);
281         glutPostRedisplay ();
282     }
283 }
284
285 int guiGetMouseButton(void)
286 {
287     return last_buttons;
288 }
289
290 void guiGetMouse(int *x, int *y)
291 {
292     *x = _mX;
293     *y = _mY;
294 };
295
296 static inline void TurnCursorOn( void )
297 {
298     mouse_active = ~0;
299 #if defined ( WIN32 ) || defined(__CYGWIN32__)
300     glutSetCursor(GLUT_CURSOR_INHERIT);
301 #endif
302 #if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9)
303     glutWarpPointer( glutGet((GLenum)GLUT_SCREEN_WIDTH)/2, glutGet((GLenum)GLUT_SCREEN_HEIGHT)/2);
304 #endif
305 }
306
307 static inline void TurnCursorOff( void )
308 {
309     mouse_active = 0;
310 #if defined ( WIN32 ) || defined(__CYGWIN32__)
311     glutSetCursor(GLUT_CURSOR_NONE);
312 #else  // I guess this is what we want to do ??
313 #if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9)
314     glutWarpPointer( glutGet((GLenum)GLUT_SCREEN_WIDTH), glutGet((GLenum)GLUT_SCREEN_HEIGHT));
315 #endif
316 #endif
317 }
318
319 void maybeToggleMouse( void )
320 {
321 #ifdef WIN32
322     static int first_time = ~0;
323     static int mouse_changed = 0;
324
325     if ( first_time ) {
326         if(!mouse_active) {
327             mouse_changed = ~mouse_changed;
328             TurnCursorOn();
329         }
330     } else {
331         if( mouse_changed ) {
332             mouse_changed = ~mouse_changed;
333             if(mouse_active) {
334                 TurnCursorOff();
335             }
336         }
337     }
338     first_time = ~first_time;
339 #endif // #ifdef WIN32
340 }
341
342 // Call with FALSE to init and TRUE to restore
343 void BusyCursor( int restore )
344 {
345     static int cursor = 0;
346     if( restore ) {
347         glutSetCursor(cursor);
348     } else {
349         cursor = glutGet( (GLenum)GLUT_WINDOW_CURSOR );
350 #ifdef WIN32
351         TurnCursorOn();
352 #endif
353         glutSetCursor( GLUT_CURSOR_WAIT );
354     }
355 }
356 /* ================ General Purpose Functions ================ */
357
358 // Intercept the Escape Key
359 void ConfirmExitDialog(void)
360 {
361     FG_PUSH_PUI_DIALOG( YNdialogBox );
362 }
363
364 // General Purpose Message Box
365 void mkDialog (const char *txt)
366 {
367     strncpy(global_dialog_string, txt, 256);
368     dialogBoxMessage->setLabel(global_dialog_string);
369     FG_PUSH_PUI_DIALOG( dialogBox );
370 }
371
372 // Repair any damage done to the Panel by other Gui Items
373 void guiFixPanel( void )
374 {
375     int toggle_pause;
376
377     if ( current_options.get_panel_status() ) {
378         FGView *v = &current_view;
379         FGTime *t = FGTime::cur_time_params;
380
381         if( (toggle_pause = !t->getPause()) )
382             t->togglePauseMode();
383
384         // this seems to be the only way to do this :-(
385         // problem is the viewport has been mucked with
386         xglViewport(0, 0 , (GLint)(v->winWidth), (GLint)(v->winHeight) );
387         FGPanel::OurPanel->ReInit(0, 0, 1024, 768);
388
389         if(toggle_pause)
390             t->togglePauseMode();
391     }
392 }
393
394 // Toggle the Menu and Mouse display state
395 void guiToggleMenu(void)
396 {
397     if( menu_on ) {
398         // printf("Hiding Menu\n");
399         mainMenuBar->hide  ();
400 #ifdef WIN32
401         TurnCursorOff();
402 #endif // #ifdef WIN32
403     } else {
404         // printf("Showing Menu\n");
405         mainMenuBar->reveal();
406 #ifdef WIN32
407         TurnCursorOn();
408 #endif // #ifdef WIN32
409     }
410     menu_on = ~menu_on;
411 }
412     
413 /* -----------------------------------------------------------------------
414 the Gui callback functions 
415 ____________________________________________________________________*/
416
417 void reInit(puObject *cb)
418 {
419     BusyCursor(0);
420     fgReInitSubsystems();
421     BusyCursor(1);
422 }
423         
424 // This is the accessor function
425 void guiTogglePanel(puObject *cb)
426 {
427     current_options.toggle_panel();
428 }
429     
430 //void MenuHideMenuCb(puObject *cb)
431 void hideMenuCb (puObject *cb)
432 {
433     guiToggleMenu();
434 }
435
436 void goodBye(puObject *)
437 {
438     // FG_LOG( FG_INPUT, FG_ALERT,
439     //      "Program exiting normally at user request." );
440     cout << "Program exiting normally at user request." << endl;
441
442     //  if(gps_bug)
443     //      fclose(gps_bug);
444
445     exit(-1);
446 }
447
448
449 void goAwayCb (puObject *me)
450 {
451     FG_POP_PUI_DIALOG( dialogBox );
452 }
453
454 void mkDialogInit (void)
455 {
456     //  printf("mkDialogInit\n");
457     int x = (current_options.get_xsize()/2 - 400/2);
458     int y = (current_options.get_ysize()/2 - 100/2);
459     dialogBox = new puDialogBox (x, y); // 150, 50
460     {
461         dialogFrame = new puFrame (0,0,400,100);
462         dialogBoxMessage  =  new puText         (10, 70);
463         dialogBoxMessage  -> setLabel           ("");
464         dialogBoxOkButton =  new puOneShot      (180, 10, 240, 50);
465         dialogBoxOkButton -> setLegend          (gui_msg_OK);
466         dialogBoxOkButton -> makeReturnDefault  (TRUE );
467         dialogBoxOkButton -> setCallback        (goAwayCb);
468     }
469     FG_FINALIZE_PUI_DIALOG( dialogBox );
470 }
471
472 void MayBeGoodBye(puObject *)
473 {
474     ConfirmExitDialog(); 
475 }
476
477 void goAwayYesNoCb(puObject *me)
478 {
479     FG_POP_PUI_DIALOG( YNdialogBox);
480 }
481
482 void ConfirmExitDialogInit(void)
483 {
484     char msg[] = "Really Quit";
485     char *s;
486
487     //  printf("ConfirmExitDialogInit\n");
488     int len = 200 - puGetStringWidth( puGetDefaultLabelFont(), msg )/2;
489
490     int x = (current_options.get_xsize()/2 - 400/2);
491     int y = (current_options.get_ysize()/2 - 100/2);
492         
493     YNdialogBox = new puDialogBox (x, y); // 150, 50
494     //  YNdialogBox = new puDialogBox (150, 50);
495     {
496         YNdialogFrame = new puFrame (0,0,400, 100);
497         
498         YNdialogBoxMessage  =  new puText         (len, 70);
499         YNdialogBoxMessage  -> setDefaultValue    (msg);
500         YNdialogBoxMessage  -> getDefaultValue    (&s);
501         YNdialogBoxMessage  -> setLabel           (s);
502         
503         YNdialogBoxOkButton =  new puOneShot      (100, 10, 160, 50);
504         YNdialogBoxOkButton -> setLegend          (gui_msg_OK);
505         YNdialogBoxOkButton -> setCallback        (goodBye);
506         
507         YNdialogBoxNoButton =  new puOneShot      (240, 10, 300, 50);
508         YNdialogBoxNoButton -> setLegend          (gui_msg_NO);
509         //      YNdialogBoxNoButton -> makeReturnDefault  (TRUE );
510         YNdialogBoxNoButton -> setCallback        (goAwayYesNoCb);
511     }
512     FG_FINALIZE_PUI_DIALOG( YNdialogBox );
513 }
514
515 void notCb (puObject *)
516 {
517     mkDialog ("This function isn't implemented yet");
518 }
519
520 void helpCb (puObject *)
521 {
522     string command;
523         
524 #if defined(FX) && !defined(WIN32)
525 #  if defined(XMESA_FX_FULLSCREEN) && defined(XMESA_FX_WINDOW)
526     if ( global_fullscreen ) {
527         global_fullscreen = false;
528         XMesaSetFXmode( XMESA_FX_WINDOW );
529     }
530 #  endif
531 #endif
532         
533 #if !defined(WIN32)
534     string url = "http://www.flightgear.org/Docs/InstallGuide/getstart.html";
535         
536     if ( system("xwininfo -name Netscape > /dev/null 2>&1") == 0 ) {
537         command = "netscape -remote \"openURL(" + url + ")\" &";
538     } else {
539         command = "netscape " + url + " &";
540     }
541 #else
542     command = "webrun.bat";
543 #endif
544         
545     system( command.c_str() );
546     //string text = "Help started in netscape window.";
547
548     //mkDialog (text.c_str());
549     mkDialog ("Help started in netscape window.");
550 }
551
552
553
554 #ifdef WIN32
555 // win32 print screen function
556 void printScreen ( puObject *obj ) {
557     bool show_pu_cursor = false;
558     TurnCursorOff();
559     if ( !puCursorIsHidden() ) {
560         show_pu_cursor = true;
561         puHideCursor();
562     }
563     BusyCursor( 0 );
564     mainMenuBar->hide();
565
566     CGlPrinter p;
567     p.Begin( "FlightGear" );
568     fgInitVisuals();
569     fgReshape( p.GetHorzRes(), p.GetVertRes() );
570     fgRenderFrame();
571     p.End();
572
573     if( menu_on ) {
574         mainMenuBar->reveal();
575     }
576     BusyCursor(1);
577     if ( show_pu_cursor ) {
578         puShowCursor();
579     }
580     TurnCursorOn();
581 }
582 #endif // #ifdef WIN32
583
584
585 // do a screen dump
586 void dumpScreen ( puObject *obj ) {
587     bool show_pu_cursor = false;
588
589     mainMenuBar->hide();
590     TurnCursorOff();
591     if ( !puCursorIsHidden() ) {
592         show_pu_cursor = true;
593         puHideCursor();
594     }
595
596     fgInitVisuals();
597     fgReshape( current_options.get_xsize(), current_options.get_ysize() );
598
599     // we need two render frames here to clear the menu and cursor
600     // ... not sure why but doing an extra fgFenderFrame() shoulnd't
601     // hurt anything
602     fgRenderFrame();
603     fgRenderFrame();
604
605     my_glDumpWindow( "fgfs-screen.ppm", 
606                      current_options.get_xsize(), 
607                      current_options.get_ysize() );
608     
609     mkDialog ("Screen dump saved to fgfs-screen.ppm");
610
611     if ( show_pu_cursor ) {
612         puShowCursor();
613     }
614
615     TurnCursorOn();
616     if( menu_on ) {
617         mainMenuBar->reveal();
618     }
619
620 }
621
622
623 /// The beginnings of teleportation :-)
624 //  Needs cleaning up but works
625 //  These statics should disapear when this is a class
626 static puDialogBox     *AptDialog = 0;
627 static puFrame         *AptDialogFrame = 0;
628 static puText          *AptDialogMessage = 0;
629 static puInput         *AptDialogInput = 0;
630
631 static char NewAirportId[16];
632 static char NewAirportLabel[] = "Enter New Airport ID"; 
633
634 static puOneShot       *AptDialogOkButton = 0;
635 static puOneShot       *AptDialogCancelButton = 0;
636 static puOneShot       *AptDialogResetButton = 0;
637
638 void AptDialog_Cancel(puObject *)
639 {
640     FG_POP_PUI_DIALOG( AptDialog );
641 }
642
643 void AptDialog_OK (puObject *)
644 {
645         fgAIRPORTS airports;
646         fgAIRPORT a;
647     
648     FGTime *t = FGTime::cur_time_params;
649     int PauseMode = t->getPause();
650     if(!PauseMode)
651         t->togglePauseMode();
652
653     char *s;
654     AptDialogInput->getValue(&s);
655     string AptId(s);
656
657         cout << "AptDialog_OK " << AptId << " " << AptId.length() << endl;
658     
659     AptDialog_Cancel( NULL );
660     
661     if ( AptId.length() ) {
662         // set initial position from airport id
663         FG_LOG( FG_GENERAL, FG_INFO,
664                 "Attempting to set starting position from airport code "
665                 << AptId );
666
667         airports.load("apt_simple");
668         if ( airports.search( AptId, &a ) )
669         {
670             current_options.set_airport_id( AptId.c_str() );
671             BusyCursor(0);
672             fgReInitSubsystems();
673             BusyCursor(1);
674         } else {
675             AptId  += " not in database.";
676             mkDialog(AptId.c_str());
677         }
678     }
679     if( PauseMode != t->getPause() )
680         t->togglePauseMode();
681 }
682
683 void AptDialog_Reset(puObject *)
684 {
685     //  strncpy( NewAirportId, current_options.get_airport_id().c_str(), 16 );
686     sprintf( NewAirportId, "%s", current_options.get_airport_id().c_str() );
687     AptDialogInput->setValue ( NewAirportId );
688     AptDialogInput->setCursor( 0 ) ;
689 }
690
691 void NewAirport(puObject *cb)
692 {
693     //  strncpy( NewAirportId, current_options.get_airport_id().c_str(), 16 );
694     sprintf( NewAirportId, "%s", current_options.get_airport_id().c_str() );
695 //      cout << "NewAirport " << NewAirportId << endl;
696     AptDialogInput->setValue( NewAirportId );
697
698     FG_PUSH_PUI_DIALOG( AptDialog );
699 }
700
701 static void NewAirportInit(void)
702 {
703     sprintf( NewAirportId, "%s", current_options.get_airport_id().c_str() );
704     int len = 150 - puGetStringWidth( puGetDefaultLabelFont(),
705                                       NewAirportLabel ) / 2;
706
707     AptDialog = new puDialogBox (150, 50);
708     {
709         AptDialogFrame   = new puFrame           (0,0,350, 150);
710         AptDialogMessage = new puText            (len, 110);
711         AptDialogMessage ->    setLabel          (NewAirportLabel);
712
713         AptDialogInput   = new puInput           (50, 70, 300, 100);
714         AptDialogInput   ->    setValue          (NewAirportId);
715         AptDialogInput   ->    acceptInput();
716
717         AptDialogOkButton     =  new puOneShot   (50, 10, 110, 50);
718         AptDialogOkButton     ->     setLegend   (gui_msg_OK);
719         AptDialogOkButton     ->     setCallback (AptDialog_OK);
720         AptDialogOkButton     ->     makeReturnDefault(TRUE);
721
722         AptDialogCancelButton =  new puOneShot   (140, 10, 210, 50);
723         AptDialogCancelButton ->     setLegend   (gui_msg_CANCEL);
724         AptDialogCancelButton ->     setCallback (AptDialog_Cancel);
725
726         AptDialogResetButton  =  new puOneShot   (240, 10, 300, 50);
727         AptDialogResetButton  ->     setLegend   (gui_msg_RESET);
728         AptDialogResetButton  ->     setCallback (AptDialog_Reset);
729     }
730         cout << "NewAirportInit " << NewAirportId << endl;
731     FG_FINALIZE_PUI_DIALOG( AptDialog );
732 }
733
734 /// The beginnings of networking :-)
735 //  Needs cleaning up but works
736 //  These statics should disapear when this is a class
737 static puDialogBox     *NetIdDialog = 0;
738 static puFrame         *NetIdDialogFrame = 0;
739 static puText          *NetIdDialogMessage = 0;
740 static puInput         *NetIdDialogInput = 0;
741
742 static char NewNetId[16];
743 static char NewNetIdLabel[] = "Enter New Callsign"; 
744
745 static puOneShot       *NetIdDialogOkButton = 0;
746 static puOneShot       *NetIdDialogCancelButton = 0;
747
748 void NetIdDialog_Cancel(puObject *)
749 {
750     FG_POP_PUI_DIALOG( NetIdDialog );
751 }
752
753 void NetIdDialog_OK (puObject *)
754 {
755     string NetId;
756     
757     FGTime *t = FGTime::cur_time_params;
758     int PauseMode = t->getPause();
759     if(!PauseMode)
760         t->togglePauseMode();
761 /*  
762    The following needs some cleanup because 
763    "string options.NetId" and "char *net_callsign" 
764 */
765     NetIdDialogInput->getValue(&net_callsign);
766     NetId = net_callsign;
767     
768     NetIdDialog_Cancel( NULL );
769     current_options.set_net_id( NetId.c_str() );
770 /* Entering a callsign indicates : user wants Net HUD Info */
771     net_hud_display = 1;
772
773     if( PauseMode != t->getPause() )
774         t->togglePauseMode();
775 }
776
777 void NewCallSign(puObject *cb)
778 {
779     sprintf( NewNetId, "%s", current_options.get_net_id().c_str() );
780     NetIdDialogInput->setValue( NewNetId );
781
782     FG_PUSH_PUI_DIALOG( NetIdDialog );
783 }
784
785 static void NewNetIdInit(void)
786 {
787     sprintf( NewNetId, "%s", current_options.get_net_id().c_str() );
788     int len = 150 - puGetStringWidth( puGetDefaultLabelFont(),
789                                       NewNetIdLabel ) / 2;
790
791     NetIdDialog = new puDialogBox (150, 50);
792     {
793         NetIdDialogFrame   = new puFrame           (0,0,350, 150);
794         NetIdDialogMessage = new puText            (len, 110);
795         NetIdDialogMessage ->    setLabel          (NewNetIdLabel);
796
797         NetIdDialogInput   = new puInput           (50, 70, 300, 100);
798         NetIdDialogInput   ->    setValue          (NewNetId);
799         NetIdDialogInput   ->    acceptInput();
800
801         NetIdDialogOkButton     =  new puOneShot   (50, 10, 110, 50);
802         NetIdDialogOkButton     ->     setLegend   (gui_msg_OK);
803         NetIdDialogOkButton     ->     setCallback (NetIdDialog_OK);
804         NetIdDialogOkButton     ->     makeReturnDefault(TRUE);
805
806         NetIdDialogCancelButton =  new puOneShot   (240, 10, 300, 50);
807         NetIdDialogCancelButton ->     setLegend   (gui_msg_CANCEL);
808         NetIdDialogCancelButton ->     setCallback (NetIdDialog_Cancel);
809
810     }
811     FG_FINALIZE_PUI_DIALOG( NetIdDialog );
812 }
813
814 static void net_display_toggle( puObject *cb)
815 {
816         net_hud_display = (net_hud_display) ? 0 : 1;
817         printf("Toggle net_hud_display : %d\n", net_hud_display);
818 }
819
820 static void net_blaster_toggle( puObject *cb)
821 {
822         net_blast_toggle = (net_blast_toggle) ? 0 : -1;
823         printf("Toggle net_blast : %d\n", net_blast_toggle);
824 }
825
826 /***************  End Networking  **************/
827
828
829
830 /* -----------------------------------------------------------------------
831 The menu stuff 
832 ---------------------------------------------------------------------*/
833 char *fileSubmenu               [] = {
834     "Exit", /* "Close", "---------", */
835 #ifdef WIN32
836     "Print",
837 #endif
838     "Screen Dump",
839     /* "---------", "Save", */ 
840     "Reset", NULL
841 };
842 puCallback fileSubmenuCb        [] = {
843     MayBeGoodBye, /* hideMenuCb, NULL, */
844 #ifdef WIN32
845     printScreen, 
846 #endif
847     /* NULL, notCb, */
848     dumpScreen,
849     reInit, NULL
850 };
851
852 /*
853 char *editSubmenu               [] = {
854     "Edit text", NULL
855 };
856 puCallback editSubmenuCb        [] = {
857     notCb, NULL
858 };
859 */
860
861 char *viewSubmenu               [] = {
862     /* "Cockpit View > ", "View >","------------", */ "Toggle Panel...", NULL
863 };
864 puCallback viewSubmenuCb        [] = {
865     /* notCb, notCb, NULL, guiTogglePanel, */ NULL
866 };
867
868 char *aircraftSubmenu           [] = {
869     "Autopilot", "Heading", "Altitude", "Navigation", "Airport", 
870     /* "Communication", */ NULL
871 };
872 puCallback aircraftSubmenuCb    [] = {
873     fgAPAdjust, NewHeading, NewAltitude, fgLatLonFormatToggle, NewTgtAirport, 
874     /* notCb, */ NULL
875 };
876
877 char *environmentSubmenu        [] = {
878     "Airport", /* "Terrain", "Weather", */ NULL
879 };
880 puCallback environmentSubmenuCb [] = {
881     NewAirport, /* notCb, notCb, */ NULL
882 };
883
884 /*
885 char *optionsSubmenu            [] = {
886     "Preferences", "Realism & Reliablity...", NULL
887 };
888 puCallback optionsSubmenuCb     [] = {
889     notCb, notCb, NULL
890 };
891 */
892
893 #ifdef FG_NETWORK_OLK
894 char *networkSubmenu            [] = {
895     /* "Unregister from FGD ", "Send MSG to All", "Send MSG", "Show Pilots", */
896     /* "Register to FGD", */
897     /* "Scan for Deamons", */ "Enter Callsign", /* "Display Netinfos", */
898     "Toggle Display",
899     "Hyper Blast", NULL
900 };
901 puCallback networkSubmenuCb     [] = {
902     /* notCb, notCb, notCb, notCb, notCb, notCb, */ NewCallSign, /* notCb, */
903     net_display_toggle, net_blaster_toggle, NULL
904 };
905 #endif
906
907 char *helpSubmenu               [] = {
908     /* "About...", */ "Help", NULL
909 };
910 puCallback helpSubmenuCb        [] = {
911     /* notCb, */ helpCb, NULL
912 };
913
914
915 /* -------------------------------------------------------------------------
916 init the gui
917 _____________________________________________________________________*/
918
919
920 void guiInit()
921 {
922     char *mesa_win_state;
923
924     // Initialize PUI
925     puInit();
926     puSetDefaultStyle         ( PUSTYLE_SMALL_BEVELLED ); //PUSTYLE_DEFAULT
927     puSetDefaultColourScheme  (0.8, 0.8, 0.8, 0.4);
928
929     // Initialize our GLOBAL GUI STRINGS
930     gui_msg_OK     = msg_OK;     // "OK"
931     gui_msg_NO     = msg_NO;     // "NO"
932     gui_msg_YES    = msg_YES;    // "YES"
933     gui_msg_CANCEL = msg_CANCEL; // "CANCEL"
934     gui_msg_RESET  = msg_RESET;  // "RESET"
935
936     // Next check home directory
937     FGPath fntpath;
938     char* envp = ::getenv( "FG_FONTS" );
939     if ( envp != NULL ) {
940         fntpath.set( envp );
941     } else {
942         fntpath.set( current_options.get_fg_root() );
943         fntpath.append( "Fonts" );
944     }
945
946     // Install our fast fonts
947     fntpath.append( "typewriter.txf" );
948     guiFntHandle = new fntTexFont ;
949     guiFntHandle -> load ( (char *)fntpath.c_str() ) ;
950     puFont GuiFont ( guiFntHandle, 15 ) ;
951     puSetDefaultFonts( GuiFont, GuiFont ) ;
952     guiFnt = puGetDefaultLabelFont();
953   
954     if ( current_options.get_mouse_pointer() == 0 ) {
955         // no preference specified for mouse pointer, attempt to autodetect...
956         // Determine if we need to render the cursor, or if the windowing
957         // system will do it.  First test if we are rendering with glide.
958         if ( strstr ( general.get_glRenderer(), "Glide" ) ) {
959             // Test for the MESA_GLX_FX env variable
960             if ( (mesa_win_state = getenv( "MESA_GLX_FX" )) != NULL) {
961                 // test if we are fullscreen mesa/glide
962                 if ( (mesa_win_state[0] == 'f') ||
963                      (mesa_win_state[0] == 'F') ) {
964                     puShowCursor ();
965                 }
966             }
967         }
968         mouse_active = ~mouse_active;
969     } else if ( current_options.get_mouse_pointer() == 1 ) {
970         // don't show pointer
971     } else if ( current_options.get_mouse_pointer() == 2 ) {
972         // force showing pointer
973         puShowCursor();
974         mouse_active = ~mouse_active;
975     }
976
977     // Set up our Dialog Boxes
978     ConfirmExitDialogInit();
979     NewAirportInit();
980 #ifdef FG_NETWORK_OLK
981     NewNetIdInit();
982 #endif
983     mkDialogInit();
984     
985     // Make the menu bar
986     mainMenuBar = new puMenuBar ();
987     mainMenuBar -> add_submenu ("File", fileSubmenu, fileSubmenuCb);
988     // mainMenuBar -> add_submenu ("Edit", editSubmenu, editSubmenuCb);
989     mainMenuBar -> add_submenu ("View", viewSubmenu, viewSubmenuCb);
990     mainMenuBar -> add_submenu ("Aircraft", aircraftSubmenu, aircraftSubmenuCb);
991     mainMenuBar -> add_submenu ("Environment", environmentSubmenu, environmentSubmenuCb);
992     // mainMenuBar -> add_submenu ("Options", optionsSubmenu, optionsSubmenuCb);
993 #ifdef FG_NETWORK_OLK
994     mainMenuBar -> add_submenu ("Network", networkSubmenu, networkSubmenuCb);
995 #endif
996     mainMenuBar -> add_submenu ("Help", helpSubmenu, helpSubmenuCb);
997     mainMenuBar-> close ();
998     // Set up menu bar toggle
999     menu_on = ~0;
1000 }