]> git.mxchange.org Git - flightgear.git/blob - src/GUI/gui.cxx
6acecfdaa613d5df116b73c47f5c60a25b9c95ed
[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     fgRenderFrame();
599     fgRenderFrame();
600
601     my_glDumpWindow( "fgfs-screen.ppm", 
602                      current_options.get_xsize(), 
603                      current_options.get_ysize() );
604     
605     mkDialog ("Screen dump saved to fgfs-screen.ppm");
606
607     if ( show_pu_cursor ) {
608         puShowCursor();
609     }
610
611     TurnCursorOn();
612     if( menu_on ) {
613         mainMenuBar->reveal();
614     }
615
616 }
617
618
619 /// The beginnings of teleportation :-)
620 //  Needs cleaning up but works
621 //  These statics should disapear when this is a class
622 static puDialogBox     *AptDialog = 0;
623 static puFrame         *AptDialogFrame = 0;
624 static puText          *AptDialogMessage = 0;
625 static puInput         *AptDialogInput = 0;
626
627 static char NewAirportId[16];
628 static char NewAirportLabel[] = "Enter New Airport ID"; 
629
630 static puOneShot       *AptDialogOkButton = 0;
631 static puOneShot       *AptDialogCancelButton = 0;
632 static puOneShot       *AptDialogResetButton = 0;
633
634 void AptDialog_Cancel(puObject *)
635 {
636     FG_POP_PUI_DIALOG( AptDialog );
637 }
638
639 void AptDialog_OK (puObject *)
640 {
641         fgAIRPORTS airports;
642         fgAIRPORT a;
643     
644     FGTime *t = FGTime::cur_time_params;
645     int PauseMode = t->getPause();
646     if(!PauseMode)
647         t->togglePauseMode();
648
649     char *s;
650     AptDialogInput->getValue(&s);
651     string AptId(s);
652
653         cout << "AptDialog_OK " << AptId << " " << AptId.length() << endl;
654     
655     AptDialog_Cancel( NULL );
656     
657     if ( AptId.length() ) {
658         // set initial position from airport id
659         FG_LOG( FG_GENERAL, FG_INFO,
660                 "Attempting to set starting position from airport code "
661                 << AptId );
662
663         airports.load("apt_simple");
664         if ( airports.search( AptId, &a ) )
665         {
666             current_options.set_airport_id( AptId.c_str() );
667             BusyCursor(0);
668             fgReInitSubsystems();
669             BusyCursor(1);
670         } else {
671             AptId  += " not in database.";
672             mkDialog(AptId.c_str());
673         }
674     }
675     if( PauseMode != t->getPause() )
676         t->togglePauseMode();
677 }
678
679 void AptDialog_Reset(puObject *)
680 {
681     //  strncpy( NewAirportId, current_options.get_airport_id().c_str(), 16 );
682     sprintf( NewAirportId, "%s", current_options.get_airport_id().c_str() );
683     AptDialogInput->setValue ( NewAirportId );
684     AptDialogInput->setCursor( 0 ) ;
685 }
686
687 void NewAirport(puObject *cb)
688 {
689     //  strncpy( NewAirportId, current_options.get_airport_id().c_str(), 16 );
690     sprintf( NewAirportId, "%s", current_options.get_airport_id().c_str() );
691 //      cout << "NewAirport " << NewAirportId << endl;
692     AptDialogInput->setValue( NewAirportId );
693
694     FG_PUSH_PUI_DIALOG( AptDialog );
695 }
696
697 static void NewAirportInit(void)
698 {
699     sprintf( NewAirportId, "%s", current_options.get_airport_id().c_str() );
700     int len = 150 - puGetStringWidth( puGetDefaultLabelFont(),
701                                       NewAirportLabel ) / 2;
702
703     AptDialog = new puDialogBox (150, 50);
704     {
705         AptDialogFrame   = new puFrame           (0,0,350, 150);
706         AptDialogMessage = new puText            (len, 110);
707         AptDialogMessage ->    setLabel          (NewAirportLabel);
708
709         AptDialogInput   = new puInput           (50, 70, 300, 100);
710         AptDialogInput   ->    setValue          (NewAirportId);
711         AptDialogInput   ->    acceptInput();
712
713         AptDialogOkButton     =  new puOneShot   (50, 10, 110, 50);
714         AptDialogOkButton     ->     setLegend   (gui_msg_OK);
715         AptDialogOkButton     ->     setCallback (AptDialog_OK);
716         AptDialogOkButton     ->     makeReturnDefault(TRUE);
717
718         AptDialogCancelButton =  new puOneShot   (140, 10, 210, 50);
719         AptDialogCancelButton ->     setLegend   (gui_msg_CANCEL);
720         AptDialogCancelButton ->     setCallback (AptDialog_Cancel);
721
722         AptDialogResetButton  =  new puOneShot   (240, 10, 300, 50);
723         AptDialogResetButton  ->     setLegend   (gui_msg_RESET);
724         AptDialogResetButton  ->     setCallback (AptDialog_Reset);
725     }
726         cout << "NewAirportInit " << NewAirportId << endl;
727     FG_FINALIZE_PUI_DIALOG( AptDialog );
728 }
729
730 /// The beginnings of networking :-)
731 //  Needs cleaning up but works
732 //  These statics should disapear when this is a class
733 static puDialogBox     *NetIdDialog = 0;
734 static puFrame         *NetIdDialogFrame = 0;
735 static puText          *NetIdDialogMessage = 0;
736 static puInput         *NetIdDialogInput = 0;
737
738 static char NewNetId[16];
739 static char NewNetIdLabel[] = "Enter New Callsign"; 
740
741 static puOneShot       *NetIdDialogOkButton = 0;
742 static puOneShot       *NetIdDialogCancelButton = 0;
743
744 void NetIdDialog_Cancel(puObject *)
745 {
746     FG_POP_PUI_DIALOG( NetIdDialog );
747 }
748
749 void NetIdDialog_OK (puObject *)
750 {
751     string NetId;
752     
753     FGTime *t = FGTime::cur_time_params;
754     int PauseMode = t->getPause();
755     if(!PauseMode)
756         t->togglePauseMode();
757 /*  
758    The following needs some cleanup because 
759    "string options.NetId" and "char *net_callsign" 
760 */
761     NetIdDialogInput->getValue(&net_callsign);
762     NetId = net_callsign;
763     
764     NetIdDialog_Cancel( NULL );
765     current_options.set_net_id( NetId.c_str() );
766 /* Entering a callsign indicates : user wants Net HUD Info */
767     net_hud_display = 1;
768
769     if( PauseMode != t->getPause() )
770         t->togglePauseMode();
771 }
772
773 void NewCallSign(puObject *cb)
774 {
775     sprintf( NewNetId, "%s", current_options.get_net_id().c_str() );
776     NetIdDialogInput->setValue( NewNetId );
777
778     FG_PUSH_PUI_DIALOG( NetIdDialog );
779 }
780
781 static void NewNetIdInit(void)
782 {
783     sprintf( NewNetId, "%s", current_options.get_net_id().c_str() );
784     int len = 150 - puGetStringWidth( puGetDefaultLabelFont(),
785                                       NewNetIdLabel ) / 2;
786
787     NetIdDialog = new puDialogBox (150, 50);
788     {
789         NetIdDialogFrame   = new puFrame           (0,0,350, 150);
790         NetIdDialogMessage = new puText            (len, 110);
791         NetIdDialogMessage ->    setLabel          (NewNetIdLabel);
792
793         NetIdDialogInput   = new puInput           (50, 70, 300, 100);
794         NetIdDialogInput   ->    setValue          (NewNetId);
795         NetIdDialogInput   ->    acceptInput();
796
797         NetIdDialogOkButton     =  new puOneShot   (50, 10, 110, 50);
798         NetIdDialogOkButton     ->     setLegend   (gui_msg_OK);
799         NetIdDialogOkButton     ->     setCallback (NetIdDialog_OK);
800         NetIdDialogOkButton     ->     makeReturnDefault(TRUE);
801
802         NetIdDialogCancelButton =  new puOneShot   (240, 10, 300, 50);
803         NetIdDialogCancelButton ->     setLegend   (gui_msg_CANCEL);
804         NetIdDialogCancelButton ->     setCallback (NetIdDialog_Cancel);
805
806     }
807     FG_FINALIZE_PUI_DIALOG( NetIdDialog );
808 }
809
810 static void net_display_toggle( puObject *cb)
811 {
812         net_hud_display = (net_hud_display) ? 0 : 1;
813         printf("Toggle net_hud_display : %d\n", net_hud_display);
814 }
815
816 static void net_blaster_toggle( puObject *cb)
817 {
818         net_blast_toggle = (net_blast_toggle) ? 0 : -1;
819         printf("Toggle net_blast : %d\n", net_blast_toggle);
820 }
821
822 /***************  End Networking  **************/
823
824
825
826 /* -----------------------------------------------------------------------
827 The menu stuff 
828 ---------------------------------------------------------------------*/
829 char *fileSubmenu               [] = {
830     "Exit", /* "Close", "---------", */
831 #ifdef WIN32
832     "Print",
833 #endif
834     "Screen Dump",
835     /* "---------", "Save", */ 
836     "Reset", NULL
837 };
838 puCallback fileSubmenuCb        [] = {
839     MayBeGoodBye, /* hideMenuCb, NULL, */
840 #ifdef WIN32
841     printScreen, 
842 #endif
843     /* NULL, notCb, */
844     dumpScreen,
845     reInit, NULL
846 };
847
848 /*
849 char *editSubmenu               [] = {
850     "Edit text", NULL
851 };
852 puCallback editSubmenuCb        [] = {
853     notCb, NULL
854 };
855 */
856
857 char *viewSubmenu               [] = {
858     /* "Cockpit View > ", "View >","------------", */ "Toggle Panel...", NULL
859 };
860 puCallback viewSubmenuCb        [] = {
861     /* notCb, notCb, NULL, guiTogglePanel, */ NULL
862 };
863
864 char *aircraftSubmenu           [] = {
865     "Autopilot", "Heading", "Altitude", "Navigation", "Airport", 
866     /* "Communication", */ NULL
867 };
868 puCallback aircraftSubmenuCb    [] = {
869     fgAPAdjust, NewHeading, NewAltitude, fgLatLonFormatToggle, NewTgtAirport, 
870     /* notCb, */ NULL
871 };
872
873 char *environmentSubmenu        [] = {
874     "Airport", /* "Terrain", "Weather", */ NULL
875 };
876 puCallback environmentSubmenuCb [] = {
877     NewAirport, /* notCb, notCb, */ NULL
878 };
879
880 /*
881 char *optionsSubmenu            [] = {
882     "Preferences", "Realism & Reliablity...", NULL
883 };
884 puCallback optionsSubmenuCb     [] = {
885     notCb, notCb, NULL
886 };
887 */
888
889 #ifdef FG_NETWORK_OLK
890 char *networkSubmenu            [] = {
891     /* "Unregister from FGD ", "Send MSG to All", "Send MSG", "Show Pilots", */
892     /* "Register to FGD", */
893     /* "Scan for Deamons", */ "Enter Callsign", /* "Display Netinfos", */
894     "Toggle Display",
895     "Hyper Blast", NULL
896 };
897 puCallback networkSubmenuCb     [] = {
898     /* notCb, notCb, notCb, notCb, notCb, notCb, */ NewCallSign, /* notCb, */
899     net_display_toggle, net_blaster_toggle, NULL
900 };
901 #endif
902
903 char *helpSubmenu               [] = {
904     /* "About...", */ "Help", NULL
905 };
906 puCallback helpSubmenuCb        [] = {
907     /* notCb, */ helpCb, NULL
908 };
909
910
911 /* -------------------------------------------------------------------------
912 init the gui
913 _____________________________________________________________________*/
914
915
916 void guiInit()
917 {
918     char *mesa_win_state;
919
920     // Initialize PUI
921     puInit();
922     puSetDefaultStyle         ( PUSTYLE_SMALL_BEVELLED ); //PUSTYLE_DEFAULT
923     puSetDefaultColourScheme  (0.8, 0.8, 0.8, 0.4);
924
925     // Initialize our GLOBAL GUI STRINGS
926     gui_msg_OK     = msg_OK;     // "OK"
927     gui_msg_NO     = msg_NO;     // "NO"
928     gui_msg_YES    = msg_YES;    // "YES"
929     gui_msg_CANCEL = msg_CANCEL; // "CANCEL"
930     gui_msg_RESET  = msg_RESET;  // "RESET"
931
932     // Next check home directory
933     FGPath fntpath;
934     char* envp = ::getenv( "FG_FONTS" );
935     if ( envp != NULL ) {
936         fntpath.set( envp );
937     } else {
938         fntpath.set( current_options.get_fg_root() );
939         fntpath.append( "Fonts" );
940     }
941
942     // Install our fast fonts
943     fntpath.append( "typewriter.txf" );
944     guiFntHandle = new fntTexFont ;
945     guiFntHandle -> load ( (char *)fntpath.c_str() ) ;
946     puFont GuiFont ( guiFntHandle, 15 ) ;
947     puSetDefaultFonts( GuiFont, GuiFont ) ;
948     guiFnt = puGetDefaultLabelFont();
949   
950     if ( current_options.get_mouse_pointer() == 0 ) {
951         // no preference specified for mouse pointer, attempt to autodetect...
952         // Determine if we need to render the cursor, or if the windowing
953         // system will do it.  First test if we are rendering with glide.
954         if ( strstr ( general.get_glRenderer(), "Glide" ) ) {
955             // Test for the MESA_GLX_FX env variable
956             if ( (mesa_win_state = getenv( "MESA_GLX_FX" )) != NULL) {
957                 // test if we are fullscreen mesa/glide
958                 if ( (mesa_win_state[0] == 'f') ||
959                      (mesa_win_state[0] == 'F') ) {
960                     puShowCursor ();
961                 }
962             }
963         }
964         mouse_active = ~mouse_active;
965     } else if ( current_options.get_mouse_pointer() == 1 ) {
966         // don't show pointer
967     } else if ( current_options.get_mouse_pointer() == 2 ) {
968         // force showing pointer
969         puShowCursor();
970         mouse_active = ~mouse_active;
971     }
972
973     // Set up our Dialog Boxes
974     ConfirmExitDialogInit();
975     NewAirportInit();
976 #ifdef FG_NETWORK_OLK
977     NewNetIdInit();
978 #endif
979     mkDialogInit();
980     
981     // Make the menu bar
982     mainMenuBar = new puMenuBar ();
983     mainMenuBar -> add_submenu ("File", fileSubmenu, fileSubmenuCb);
984     // mainMenuBar -> add_submenu ("Edit", editSubmenu, editSubmenuCb);
985     mainMenuBar -> add_submenu ("View", viewSubmenu, viewSubmenuCb);
986     mainMenuBar -> add_submenu ("Aircraft", aircraftSubmenu, aircraftSubmenuCb);
987     mainMenuBar -> add_submenu ("Environment", environmentSubmenu, environmentSubmenuCb);
988     // mainMenuBar -> add_submenu ("Options", optionsSubmenu, optionsSubmenuCb);
989 #ifdef FG_NETWORK_OLK
990     mainMenuBar -> add_submenu ("Network", networkSubmenu, networkSubmenuCb);
991 #endif
992     mainMenuBar -> add_submenu ("Help", helpSubmenu, helpSubmenuCb);
993     mainMenuBar-> close ();
994     // Set up menu bar toggle
995     menu_on = ~0;
996 }