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