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