OSDN Git Service

guarantee an alter on oracle
[nethackexpress/trunk.git] / win / gnome / gnmain.c
1 /*      SCCS Id: @(#)gnmain.c   3.4     2000/07/16      */
2 /* Copyright (C) 1998 by Erik Andersen <andersee@debian.org> */
3 /* NetHack may be freely redistributed.  See license for details. */
4
5 #include "gnmain.h"
6 #include "gnsignal.h"
7 #include "gnbind.h"
8 #include "gnopts.h"
9 #include <gnome.h>
10 #include <getopt.h>
11 #include <gdk/gdk.h>
12 #include <sys/time.h>
13 #include <unistd.h>
14 #include <signal.h>
15 #include "hack.h"
16 #include "date.h"
17
18 static GtkWidget* mainWindow=NULL;
19 static GtkWidget *about=NULL;
20 static GtkWidget* hBoxFirstRow;
21 static GtkWidget* vBoxMain;
22
23 int restarted = 0;
24 int os_x = 0, os_y = 0, os_w = 0, os_h = 0;
25
26
27 static GnomeClient *session_id;
28
29 static
30 void ghack_quit_game(GtkWidget *widget, int button)
31 {
32     gtk_widget_hide(widget);
33     if (button == 0) {
34         gnome_exit_nhwindows(0);
35         gtk_object_unref(GTK_OBJECT(session_id));
36     }
37 }
38
39 static
40 void ghack_quit_game_cb(GtkWidget *widget, gpointer data)
41 {
42     GtkWidget *box;
43     box = gnome_message_box_new(_("Do you really want to quit?"), 
44             GNOME_MESSAGE_BOX_QUESTION, GNOME_STOCK_BUTTON_YES, 
45             GNOME_STOCK_BUTTON_NO, NULL);
46     gnome_dialog_set_default( GNOME_DIALOG(box), 1);
47     gnome_dialog_set_parent (GNOME_DIALOG (box), 
48             GTK_WINDOW (ghack_get_main_window ()) );
49     gnome_dialog_set_accelerator (GNOME_DIALOG(box), 1, 'n', 0);
50     gnome_dialog_set_accelerator (GNOME_DIALOG(box), 0, 'y', 0);
51
52     gtk_window_set_modal( GTK_WINDOW(box), TRUE);
53     gtk_signal_connect( GTK_OBJECT(box), "clicked", 
54             (GtkSignalFunc)ghack_quit_game, NULL);
55     gtk_widget_show(box);
56 }
57
58 static
59 void ghack_save_game(GtkWidget *widget, int button)
60 {
61     gtk_widget_hide(widget);
62     if (button == 0) {
63         if(dosave0()) {
64             /* make sure they see the Saving message */
65             display_nhwindow(WIN_MESSAGE, TRUE);
66             gnome_exit_nhwindows("Be seeing you...");
67         } else (void)doredraw();
68     }
69 }
70
71 void ghack_save_game_cb(GtkWidget *widget, gpointer data)
72 {
73     GtkWidget *box;
74     box = gnome_message_box_new(_("Quit and save the current game?"), 
75             GNOME_MESSAGE_BOX_QUESTION, GNOME_STOCK_BUTTON_YES, 
76             GNOME_STOCK_BUTTON_NO, NULL);
77     gnome_dialog_set_default( GNOME_DIALOG(box), 1);
78     gnome_dialog_set_parent (GNOME_DIALOG (box), 
79             GTK_WINDOW (ghack_get_main_window ()) );
80     gnome_dialog_set_accelerator (GNOME_DIALOG(box), 1, 'n', 0);
81     gnome_dialog_set_accelerator (GNOME_DIALOG(box), 0, 'y', 0);
82
83     gtk_window_set_modal( GTK_WINDOW(box), TRUE);
84     gtk_signal_connect( GTK_OBJECT(box), "clicked", 
85             (GtkSignalFunc)ghack_save_game, NULL);
86     gtk_widget_show(box);
87 }
88
89 static
90 void ghack_new_game(GtkWidget *widget, int button)
91 {
92     if (button == 0) {
93         g_message("This feature is not yet implemented.  Sorry.");
94     }
95 }
96
97 static
98 void ghack_new_game_cb(GtkWidget *widget, gpointer data)
99 {
100     GtkWidget *box;
101     box = gnome_message_box_new(_("Start a new game?"), 
102             GNOME_MESSAGE_BOX_QUESTION, GNOME_STOCK_BUTTON_YES, 
103             GNOME_STOCK_BUTTON_NO, NULL);
104     gnome_dialog_set_default( GNOME_DIALOG(box), 1);
105     gnome_dialog_set_parent (GNOME_DIALOG (box), 
106             GTK_WINDOW (ghack_get_main_window ()) );
107     gnome_dialog_set_accelerator (GNOME_DIALOG(box), 1, 'n', 0);
108     gnome_dialog_set_accelerator (GNOME_DIALOG(box), 0, 'y', 0);
109
110     gtk_window_set_modal( GTK_WINDOW(box), TRUE);
111     gtk_signal_connect( GTK_OBJECT(box), "clicked", 
112             (GtkSignalFunc)ghack_new_game, NULL);
113     gtk_widget_show(box);
114 }
115
116 static void
117 about_destroy_callback (void)
118 {
119     about = NULL;
120 }
121
122 static void 
123 ghack_about_cb(GtkWidget *widget, gpointer data)
124 {
125     char buf[BUFSZ]="\0";
126     char buf1[BUFSZ]="\0";
127     const gchar *authors[] = {"Erik Andersen", "Anthony Taylor", 
128         "Jeff Garzik", "The Nethack Dev Team", NULL};
129
130     if (about) {
131         gdk_window_raise (about->window);
132         return;
133     }
134
135     getversionstring(buf);
136     strcat( buf1, VERSION_STRING);
137     strcat( buf, 
138       _("\nSend comments and bug reports to: nethack-bugs@nethack.org\n"
139       "This game is free software. See License for details."));
140     about = gnome_about_new(_("Nethack"), 
141             buf1, "Copyright (C) 1985-2002 Mike Stephenson",
142             (const char **)authors, buf,
143             NULL);
144
145     gtk_signal_connect (GTK_OBJECT (about), "destroy",
146         (GtkSignalFunc) about_destroy_callback, NULL);
147     
148     gtk_widget_show(about);
149 }
150
151 static void 
152 ghack_settings_cb(GtkWidget *widget, gpointer data)
153 {
154     ghack_settings_dialog();
155 }
156
157 static void 
158 ghack_accelerator_selected (GtkWidget *widget, gpointer data)
159 {
160     GdkEventKey event;
161     int key = GPOINTER_TO_INT( data); 
162     /* g_message("An accelerator for \"%c\" was selected", key); */
163     /* stuff a key directly into the keybuffer */
164     event.state=0;
165     event.keyval=key;
166     ghack_handle_key_press(NULL, &event, NULL);
167 }
168
169 #ifndef M
170 # ifndef NHSTDC
171 #  define M(c)          (0x80 | (c))
172 # else
173 #  define M(c)          ((c) - 128)
174 # endif /* NHSTDC */
175 #endif
176 #ifndef C
177 #define C(c)            (0x1f & (c))
178 #endif
179
180
181 GnomeUIInfo game_tree[] = 
182 {
183     {
184         GNOME_APP_UI_ITEM, N_ ("_Change Settings..."), 
185         N_("Change Game Settings"), ghack_settings_cb, NULL, NULL, 
186         GNOME_APP_PIXMAP_NONE, NULL, 0,0, NULL
187     },
188     GNOMEUIINFO_SEPARATOR,
189     { 
190         GNOME_APP_UI_ITEM, N_("Version"), NULL, 
191         ghack_accelerator_selected, GINT_TO_POINTER('v'), NULL, 
192         GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_ABOUT, 'v',0 
193     }, 
194     { 
195         GNOME_APP_UI_ITEM, N_("History..."), NULL, 
196         ghack_accelerator_selected, GINT_TO_POINTER('V'), NULL, 
197         GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_ABOUT, 'V',GDK_SHIFT_MASK 
198     }, 
199     { 
200         GNOME_APP_UI_ITEM, N_("Compilation..."), NULL, 
201         ghack_accelerator_selected, GINT_TO_POINTER(M('v')), NULL, 
202         GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_ABOUT,'v',GDK_MOD1_MASK
203     }, 
204     { 
205         GNOME_APP_UI_ITEM, N_("Options..."), NULL, 
206         ghack_accelerator_selected, GINT_TO_POINTER('O'), NULL, 
207         GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_PREF, 'O', GDK_SHIFT_MASK
208     }, 
209     { 
210         GNOME_APP_UI_ITEM, N_("Explore Mode..."), NULL, 
211         ghack_accelerator_selected, GINT_TO_POINTER('X'), NULL, 
212         GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_QUIT, 'X', GDK_SHIFT_MASK
213     }, 
214     GNOMEUIINFO_SEPARATOR,
215     GNOMEUIINFO_MENU_NEW_GAME_ITEM(ghack_new_game_cb, NULL),
216     GNOMEUIINFO_MENU_SAVE_ITEM(ghack_save_game_cb, NULL),
217     { 
218         GNOME_APP_UI_ITEM, N_("Exit"), NULL, 
219         ghack_quit_game_cb, GINT_TO_POINTER(M('Q')), NULL, 
220         GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_ABOUT, 'Q', GDK_MOD1_MASK
221     }, 
222     GNOMEUIINFO_END
223 };
224
225
226
227 GnomeUIInfo edit_menu[] = {
228            { 
229                GNOME_APP_UI_ITEM, N_("Inventory"), 
230                N_("Edit/View your Inventory"), ghack_accelerator_selected, 
231                GINT_TO_POINTER('i'), NULL, GNOME_APP_PIXMAP_NONE, NULL, 'i', 0
232            },
233            { 
234                GNOME_APP_UI_ITEM, N_("Discoveries"), 
235                N_("Edit/View your Discoveries"),
236                ghack_accelerator_selected, 
237                GINT_TO_POINTER('\\'), NULL, GNOME_APP_PIXMAP_NONE, NULL, '\\',0
238            },
239            { 
240                GNOME_APP_UI_ITEM, N_("List/reorder your spells"), 
241                N_("List/reorder your spells"), ghack_accelerator_selected, 
242                GINT_TO_POINTER('x'), NULL, GNOME_APP_PIXMAP_NONE, NULL, 'x', 0
243            },
244            { 
245                GNOME_APP_UI_ITEM, N_("Adjust letters"), 
246                N_("Adjust letter for items in your Inventory"), ghack_accelerator_selected, 
247                 GINT_TO_POINTER(M('a')), NULL, GNOME_APP_PIXMAP_NONE, NULL, 'a', GDK_MOD1_MASK
248            },
249            GNOMEUIINFO_SEPARATOR,
250            { 
251                GNOME_APP_UI_ITEM, N_("Name object"), 
252                N_("Assign a name to an object"), ghack_accelerator_selected, 
253                GINT_TO_POINTER(M('n')), NULL, GNOME_APP_PIXMAP_NONE, NULL, 'n', GDK_MOD1_MASK
254            },
255            { 
256                GNOME_APP_UI_ITEM, N_("Name creature"), 
257                N_("Assign a name to a creature"), ghack_accelerator_selected, 
258                GINT_TO_POINTER('C'), NULL, GNOME_APP_PIXMAP_NONE, NULL, 'C', GDK_SHIFT_MASK
259            },
260            GNOMEUIINFO_SEPARATOR,
261            { 
262                GNOME_APP_UI_ITEM, N_("Qualifications"), 
263                N_("Edit your Qualifications"), ghack_accelerator_selected, 
264                GINT_TO_POINTER(M('e')), NULL, GNOME_APP_PIXMAP_NONE, NULL, 'e',GDK_MOD1_MASK
265            },
266            GNOMEUIINFO_END
267 };
268
269
270 GnomeUIInfo apparel_menu[] = {
271            { 
272                GNOME_APP_UI_ITEM, N_("Wield Weapon"), 
273                N_("Select a weapon to fight with"),
274                ghack_accelerator_selected, 
275                GINT_TO_POINTER('w'), NULL, GNOME_APP_PIXMAP_NONE, NULL, 'w',0
276            },
277            { 
278                GNOME_APP_UI_ITEM, N_("Remove Apparel..."), 
279                N_("Remove apparel dialog bog"), ghack_accelerator_selected, 
280                GINT_TO_POINTER('A'), NULL, GNOME_APP_PIXMAP_NONE, NULL, 'A',GDK_SHIFT_MASK
281            },
282            GNOMEUIINFO_SEPARATOR,
283            { 
284                GNOME_APP_UI_ITEM, N_("Wear Armor"), 
285                N_("Put on armor"), ghack_accelerator_selected, 
286                GINT_TO_POINTER('W'), NULL, GNOME_APP_PIXMAP_NONE, NULL, 'W',GDK_SHIFT_MASK
287            },
288            { 
289                GNOME_APP_UI_ITEM, N_("Take off Armor"), 
290                N_("Take off armor you are wearing"), ghack_accelerator_selected, 
291                GINT_TO_POINTER('T'), NULL, GNOME_APP_PIXMAP_NONE, NULL, 'T',GDK_SHIFT_MASK
292            },
293            GNOMEUIINFO_SEPARATOR,
294            { 
295                GNOME_APP_UI_ITEM, N_("Put on non-armor"), 
296                N_("Put on non-armor apparel"), ghack_accelerator_selected, 
297                GINT_TO_POINTER('P'), NULL, GNOME_APP_PIXMAP_NONE, NULL, 'P',GDK_SHIFT_MASK
298            },
299            { 
300                GNOME_APP_UI_ITEM, N_("Remove non-armor"), 
301                N_("Remove non-armor apparel you are wearing"), ghack_accelerator_selected, 
302                GINT_TO_POINTER('R'), NULL, GNOME_APP_PIXMAP_NONE, NULL, 'R',GDK_SHIFT_MASK
303            },
304            GNOMEUIINFO_END
305 };
306
307 GnomeUIInfo action_menu[] = {
308            { 
309                GNOME_APP_UI_ITEM, N_("Get"), 
310                N_("Pick up things at the current location"), 
311                ghack_accelerator_selected, 
312                GINT_TO_POINTER(','), NULL, GNOME_APP_PIXMAP_NONE, NULL, ',',0
313            },
314            { 
315                GNOME_APP_UI_ITEM, N_("Loot"), 
316                N_("loot a box on the floor"), 
317                ghack_accelerator_selected, 
318                GINT_TO_POINTER(M('l')), NULL, GNOME_APP_PIXMAP_NONE, NULL, 'l',GDK_MOD1_MASK
319            },
320            { 
321                GNOME_APP_UI_ITEM, N_("Sit"), 
322                N_("sit down"), 
323                ghack_accelerator_selected, 
324                GINT_TO_POINTER(M('s')), NULL, GNOME_APP_PIXMAP_NONE, NULL, 's',GDK_MOD1_MASK
325            },
326            { 
327                GNOME_APP_UI_ITEM, N_("Force"), 
328                N_("force a lock"), 
329                ghack_accelerator_selected, 
330                GINT_TO_POINTER(M('f')), NULL, GNOME_APP_PIXMAP_NONE, NULL, 'f',GDK_MOD1_MASK
331            },
332            { 
333                GNOME_APP_UI_ITEM, N_("Kick"), 
334                N_("kick something (usually a door)"), 
335                ghack_accelerator_selected, 
336                GINT_TO_POINTER(C('d')), NULL, GNOME_APP_PIXMAP_NONE, NULL, 'd',GDK_CONTROL_MASK
337            },
338            { 
339                GNOME_APP_UI_ITEM, N_("Jump"), 
340                N_("jump to another location"),
341                ghack_accelerator_selected, 
342                GINT_TO_POINTER(M('j')), NULL, GNOME_APP_PIXMAP_NONE, NULL, 'j',GDK_MOD1_MASK
343            },
344 #ifdef STEED
345            { 
346                GNOME_APP_UI_ITEM, N_("Ride"), 
347                N_("Ride (or stop riding) a monster"),
348                doride, 
349                GINT_TO_POINTER(M('r')), NULL, GNOME_APP_PIXMAP_NONE, NULL, 'R',GDK_MOD1_MASK
350            },
351 #endif
352            { 
353                GNOME_APP_UI_ITEM, N_("Wipe face"), 
354                N_("wipe off your face"),
355                ghack_accelerator_selected, 
356                GINT_TO_POINTER(M('w')), NULL, GNOME_APP_PIXMAP_NONE, NULL, 'w',GDK_MOD1_MASK
357            },
358            { 
359                GNOME_APP_UI_ITEM, N_("Throw/Shoot"), 
360                N_("throw or shoot a weapon"),
361                ghack_accelerator_selected, 
362                GINT_TO_POINTER('t'), NULL, GNOME_APP_PIXMAP_NONE, NULL, 't',0
363            },
364            {
365                GNOME_APP_UI_ITEM, N_("Quiver/Ready"),
366                N_("ready or quiver some ammunition"),
367                ghack_accelerator_selected,
368                GINT_TO_POINTER('Q'), NULL, GNOME_APP_PIXMAP_NONE, NULL, 'Q',GDK_SHIFT_MASK,
369            },
370            { 
371                GNOME_APP_UI_ITEM, N_("Open Door"), 
372                N_("open a door"),
373                ghack_accelerator_selected, 
374                GINT_TO_POINTER('o'), NULL, GNOME_APP_PIXMAP_NONE, NULL, 'o',0
375            },
376            { 
377                GNOME_APP_UI_ITEM, N_("Close Door"), 
378                N_("open a door"),
379                ghack_accelerator_selected, 
380                GINT_TO_POINTER('c'), NULL, GNOME_APP_PIXMAP_NONE, NULL, 'c',0
381            },
382            GNOMEUIINFO_SEPARATOR,
383            { 
384                GNOME_APP_UI_ITEM, N_("Drop"), 
385                N_("drop an object"),
386                ghack_accelerator_selected, 
387                GINT_TO_POINTER('d'), NULL, GNOME_APP_PIXMAP_NONE, NULL, 'd',0
388            },
389            { 
390                GNOME_APP_UI_ITEM, N_("Drop Many"), 
391                N_("drop selected types of objects"),
392                ghack_accelerator_selected, 
393                GINT_TO_POINTER('D'), NULL, GNOME_APP_PIXMAP_NONE, NULL, 'D',GDK_SHIFT_MASK
394            },
395            { 
396                GNOME_APP_UI_ITEM, N_("Eat"), 
397                N_("eat something"),
398                ghack_accelerator_selected, 
399                GINT_TO_POINTER('e'), NULL, GNOME_APP_PIXMAP_NONE, NULL, 'e',0
400            },
401            { 
402                GNOME_APP_UI_ITEM, N_("Engrave"), 
403                N_("write a message in the dust on the floor"),
404                ghack_accelerator_selected, 
405                GINT_TO_POINTER('E'), NULL, GNOME_APP_PIXMAP_NONE, NULL, 'E',GDK_SHIFT_MASK
406            },
407            { 
408                GNOME_APP_UI_ITEM, N_("Apply"), 
409                N_("apply or use a tool (pick-axe, key, camera, etc.)"),
410                ghack_accelerator_selected, 
411                GINT_TO_POINTER('a'), NULL, GNOME_APP_PIXMAP_NONE, NULL, 'a',0
412            },
413            GNOMEUIINFO_SEPARATOR,
414            { 
415                GNOME_APP_UI_ITEM, N_("Up"), 
416                N_("go up the stairs"),
417                ghack_accelerator_selected, 
418                GINT_TO_POINTER('<'), NULL, GNOME_APP_PIXMAP_NONE, NULL, '<',0
419            },
420            { 
421                GNOME_APP_UI_ITEM, N_("Down"), 
422                N_("go down the stairs"),
423                ghack_accelerator_selected, 
424                GINT_TO_POINTER('>'), NULL, GNOME_APP_PIXMAP_NONE, NULL, '>',0
425            },
426            { 
427                GNOME_APP_UI_ITEM, N_("Rest"), 
428                N_("wait for a moment"),
429                ghack_accelerator_selected, 
430                GINT_TO_POINTER('.'), NULL, GNOME_APP_PIXMAP_NONE, NULL, '.',0
431            },
432            { 
433                GNOME_APP_UI_ITEM, N_("Search"), 
434                N_("search for secret doors, hidden traps and monsters"),
435                ghack_accelerator_selected, 
436                GINT_TO_POINTER('s'), NULL, GNOME_APP_PIXMAP_NONE, NULL, 's',0
437            },
438            GNOMEUIINFO_SEPARATOR,
439            { 
440                GNOME_APP_UI_ITEM, N_("Chat"), 
441                N_("talk to someone"),
442                ghack_accelerator_selected, 
443                GINT_TO_POINTER(M('c')), NULL, GNOME_APP_PIXMAP_NONE, NULL, 'c',GDK_MOD1_MASK
444            },
445            { 
446                GNOME_APP_UI_ITEM, N_("Pay"), 
447                N_("pay your bill to the shopkeeper"),
448                ghack_accelerator_selected, 
449                GINT_TO_POINTER('p'), NULL, GNOME_APP_PIXMAP_NONE, NULL, 'p',0
450            },
451            GNOMEUIINFO_END
452 };
453
454 GnomeUIInfo magic_menu[] = {
455            { 
456                GNOME_APP_UI_ITEM, N_("Quaff potion"), 
457                N_("drink a potion"), 
458                ghack_accelerator_selected, 
459                GINT_TO_POINTER('q'), NULL, GNOME_APP_PIXMAP_NONE, NULL, 'q',0
460            },
461            { 
462                GNOME_APP_UI_ITEM, N_("Read Book/Scroll"), 
463                N_("read a spell book or a scroll"), 
464                ghack_accelerator_selected, 
465                GINT_TO_POINTER('r'), NULL, GNOME_APP_PIXMAP_NONE, NULL, 'r',0
466            },
467            { 
468                GNOME_APP_UI_ITEM, N_("Zap Wand"), 
469                N_("zap a wand"),
470                ghack_accelerator_selected, 
471                GINT_TO_POINTER('z'), NULL, GNOME_APP_PIXMAP_NONE, NULL, 'z',0
472            },
473            { 
474                GNOME_APP_UI_ITEM, N_("Zap Spell"), 
475                N_("cast a spell"),
476                ghack_accelerator_selected, 
477                GINT_TO_POINTER('Z'), NULL, GNOME_APP_PIXMAP_NONE, NULL, 'Z',GDK_SHIFT_MASK
478            },
479            GNOMEUIINFO_SEPARATOR,
480            { 
481                GNOME_APP_UI_ITEM, N_("Dip"), 
482                N_("dip an object into something"),
483                ghack_accelerator_selected, 
484                GINT_TO_POINTER(M('d')), NULL, GNOME_APP_PIXMAP_NONE, NULL, 'd',GDK_MOD1_MASK
485            },
486            { 
487                GNOME_APP_UI_ITEM, N_("Rub"), 
488                N_("Rub something (i.e. a lamp)"),
489                ghack_accelerator_selected, 
490                GINT_TO_POINTER(M('r')), NULL, GNOME_APP_PIXMAP_NONE, NULL, 'r',GDK_MOD1_MASK
491            },
492            { 
493                GNOME_APP_UI_ITEM, N_("Invoke"), 
494                N_("invoke an object's special powers"),
495                ghack_accelerator_selected, 
496                GINT_TO_POINTER(M('i')), NULL, GNOME_APP_PIXMAP_NONE, NULL, 'i',GDK_MOD1_MASK
497            },
498            GNOMEUIINFO_SEPARATOR,
499            { 
500                GNOME_APP_UI_ITEM, N_("Offer"), 
501                N_("offer a sacrifice to the gods"),
502                ghack_accelerator_selected, 
503                GINT_TO_POINTER(M('o')), NULL, GNOME_APP_PIXMAP_NONE, NULL, 'o',GDK_MOD1_MASK
504            },
505            { 
506                GNOME_APP_UI_ITEM, N_("Pray"), 
507                N_("pray to the gods for help"),
508                ghack_accelerator_selected, 
509                GINT_TO_POINTER(M('p')), NULL, GNOME_APP_PIXMAP_NONE, NULL, 'p',GDK_MOD1_MASK
510            },
511            GNOMEUIINFO_SEPARATOR,
512            { 
513                GNOME_APP_UI_ITEM, N_("Teleport"), 
514                N_("teleport (if you can)"),
515                ghack_accelerator_selected, 
516                GINT_TO_POINTER(C('t')), NULL, GNOME_APP_PIXMAP_NONE, NULL, 't',GDK_CONTROL_MASK
517            },
518            { 
519                GNOME_APP_UI_ITEM, N_("Monster Action"), 
520                N_("use a monster's special ability"),
521                ghack_accelerator_selected, 
522                GINT_TO_POINTER(M('m')), NULL, GNOME_APP_PIXMAP_NONE, NULL, 'm',GDK_MOD1_MASK
523            },
524            { 
525                GNOME_APP_UI_ITEM, N_("Turn Undead"), 
526                N_("turn undead"),
527                ghack_accelerator_selected, 
528                GINT_TO_POINTER(M('t')), NULL, GNOME_APP_PIXMAP_NONE, NULL, 't',GDK_MOD1_MASK
529            },
530            GNOMEUIINFO_END
531 };
532
533 GnomeUIInfo help_menu[] = {
534             { 
535                 GNOME_APP_UI_ITEM, N_("About..."), 
536                 N_("About GnomeHack"), ghack_about_cb, NULL, NULL, 
537                 GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_ABOUT, 0, 0, NULL 
538             }, 
539            { 
540                GNOME_APP_UI_ITEM, N_("Help"), NULL,
541                ghack_accelerator_selected, 
542                GINT_TO_POINTER('?'), NULL, GNOME_APP_PIXMAP_STOCK, 
543                GNOME_STOCK_MENU_ABOUT, '?', 0
544            },
545            GNOMEUIINFO_SEPARATOR,
546            { 
547                GNOME_APP_UI_ITEM, N_("What is here"), 
548                N_("Check what items occupy the current location"),
549                ghack_accelerator_selected, 
550                GINT_TO_POINTER(':'), NULL, GNOME_APP_PIXMAP_STOCK, 
551                GNOME_STOCK_MENU_ABOUT, ':',0
552            },
553            { 
554                GNOME_APP_UI_ITEM, N_("What is that"), 
555                N_("Identify an object"),
556                ghack_accelerator_selected, 
557                GINT_TO_POINTER(';'), NULL, GNOME_APP_PIXMAP_STOCK, 
558                GNOME_STOCK_MENU_ABOUT, ';',0
559            },
560            { 
561                GNOME_APP_UI_ITEM, N_("Identify a map symbol"), 
562                N_("Identify a map symbol"),
563                ghack_accelerator_selected, 
564                GINT_TO_POINTER('/'), NULL, GNOME_APP_PIXMAP_STOCK, 
565                GNOME_STOCK_MENU_ABOUT, '/',0
566            },
567            GNOMEUIINFO_END 
568 };
569             
570 GnomeUIInfo mainmenu[] = {
571             GNOMEUIINFO_MENU_GAME_TREE(game_tree),
572             GNOMEUIINFO_MENU_EDIT_TREE(edit_menu),
573             { GNOME_APP_UI_SUBTREE, N_("Apparel"), NULL, apparel_menu, NULL, 
574                 NULL, 0, NULL, 0, 0, NULL },
575             { GNOME_APP_UI_SUBTREE, N_("Action"), NULL, action_menu, NULL, 
576                 NULL, 0, NULL, 0, 0, NULL },
577             { GNOME_APP_UI_SUBTREE, N_("Magic"), NULL, magic_menu, NULL, 
578                 NULL, 0, NULL, 0, 0, NULL },
579             GNOMEUIINFO_MENU_HELP_TREE(help_menu),
580             GNOMEUIINFO_END
581 };
582
583 static void
584 ghack_main_window_key_press(GtkWidget *widget, GdkEventKey *event, 
585         gpointer data)
586 {
587     /* First, turn off the key press propogation.  We've got the
588      * key, but we don't wan't the underlying Gtk widgets to get it,
589      * since they do the wrong thing with the arrow keys (shift focus)... */
590     gtk_signal_emit_stop_by_name( GTK_OBJECT(mainWindow), "key_press_event");
591     
592     /* stuff the key event into the keybuffer */
593     ghack_handle_key_press(widget, event, data);
594 }
595
596
597 /* parsing args */
598 void
599 parse_args (int argc, char *argv[])
600 {
601   gint ch;
602
603   struct option options[] = {
604         /* Default args */
605         { "help",               no_argument,            NULL,   'h'     },
606         { "version",            no_argument,            NULL,   'v'     },
607
608         { NULL, 0, NULL, 0 }
609         };
610
611   gchar *id = NULL;
612
613   /* initialize getopt */
614   optarg = NULL;
615   optind = 0;
616   optopt = 0;
617
618   while( (ch = getopt_long(argc, argv, "hv", options, NULL)) != EOF )
619   {
620     switch(ch)
621     {
622       case 'h':
623         g_print ( 
624           _("%s: A gnomified 'Hello World' program\n\n"
625             "Usage: %s [--help] [--version]\n\n"
626             "Options:\n"
627             "        --help     display this help and exit\n"
628             "        --version  output version information and exit\n"),
629             argv[0], argv[0]);
630         exit(0);
631         break;
632       case 'v':
633         g_print (_("NetHack %s.\n"), VERSION_STRING);
634         exit(0);
635         break;
636       case ':':
637       case '?':
638         g_print (_("Options error\n"));
639         exit(0);
640         break;
641     }
642   }
643
644   /* SM stuff */
645   session_id = gnome_client_new ();
646 #if 0
647   session_id = gnome_client_new (
648         /* callback to save the state and parameter for it */
649         save_state, argv[0], 
650         /* callback to die and parameter for it */
651         NULL, NULL,
652         /* id from the previous session if restarted, NULL otherwise */
653         id);
654 #endif
655   /* set the program name */
656   gnome_client_set_program (session_id, argv[0]);
657   g_free(id);
658
659   return;
660 }
661
662 /*
663  * [ALI] Gnome installs its own handler(s) for SIGBUS, SIGFPE and SIGSEGV.
664  * These handlers will fork and exec a helper program. When that helper
665  * comes to initialize GTK+, it may fail if setuid/setgid. We solve this
666  * by dropping privileges before passing the signal along the chain.
667  * Note: We don't need to either drop or mask the saved ID since this
668  * will be reset when the child process performs the execve() anyway.
669  */
670
671 static struct {
672     int signum;
673     void (*handler)(int);
674 } ghack_chain[] = {
675     {SIGBUS},
676     {SIGFPE},
677     {SIGSEGV},
678     {SIGILL}            /* Not currently handled by Gnome */
679 };
680
681 static void ghack_sig_handler(int signum)
682 {
683     int i;
684     uid_t uid, euid;
685     gid_t gid, egid;
686     uid = getuid();
687     euid = geteuid();
688     gid = getgid();
689     egid = getegid();
690     if (gid != egid)
691         setgid(gid);
692     if (uid != euid)
693         setuid(uid);
694     for(i = SIZE(ghack_chain) - 1; i >= 0; i--)
695         if (ghack_chain[i].signum == signum) {
696             ghack_chain[i].handler(signum);
697             break;
698         }
699     if (i < 0)
700         impossible("Unhandled ghack signal");
701     if (uid != euid)
702         setuid(euid);
703     if (gid != egid)
704         setgid(egid);
705 }
706
707 /* initialize gnome and fir up the main window */
708 void ghack_init_main_window( int argc, char** argv)
709 {
710     int i;
711     struct timeval tv;
712     uid_t uid, euid;
713
714     /* It seems that the authors of gnome_score_init() drop group
715      * priveledges.  We need group priveledges, so until we change the
716      * way we save games to do things the gnome way(???), this stays
717      * commented out.  (after hours of frusteration...)
718      *  -Erik
719      */
720     /* gnome_score_init("gnomehack"); */
721
722     gettimeofday(&tv, NULL);
723     srand(tv.tv_usec);
724
725     uid = getuid();
726     euid = geteuid();
727     if (uid != euid)
728       setuid(uid);
729     hide_privileges(TRUE);
730     /* XXX gnome_init must print nethack options for --help, but does not */
731     gnome_init ("nethack", VERSION_STRING, argc, argv);
732     hide_privileges(FALSE);
733     parse_args (argc, argv);
734
735     /* Initialize the i18n stuff (not that gnomehack supperts it yet...) */
736 #if 0
737     textdomain (PACKAGE);
738 #endif
739     gdk_imlib_init();
740
741     /* Main window */
742     mainWindow = gnome_app_new((char *) "nethack", 
743             (char *) N_("Nethack for Gnome"));
744     gtk_widget_realize(mainWindow);
745     if (restarted) {
746         gtk_widget_set_uposition (mainWindow, os_x, os_y);
747         gtk_widget_set_usize     (mainWindow, os_w, os_h);
748     }
749     gtk_window_set_default_size( GTK_WINDOW(mainWindow), 800, 600);
750     gtk_window_set_policy(GTK_WINDOW(mainWindow), FALSE, TRUE, TRUE);
751     gnome_app_create_menus(GNOME_APP(mainWindow), mainmenu);
752     gtk_signal_connect(GTK_OBJECT(mainWindow), "key_press_event", 
753             GTK_SIGNAL_FUNC(ghack_main_window_key_press), NULL);
754     gtk_signal_connect(GTK_OBJECT(mainWindow), "delete_event", 
755             GTK_SIGNAL_FUNC(ghack_quit_game_cb), NULL);
756
757     /* Put some stuff into our main window */
758     vBoxMain = gtk_vbox_new (FALSE, 0);
759     hBoxFirstRow = gtk_hbox_new (FALSE, 0);
760    
761     /* pack Boxes into other boxes to produce the right structure */
762     gtk_box_pack_start (GTK_BOX (vBoxMain), hBoxFirstRow, FALSE, TRUE, 0);   
763     
764     /* pack vBoxMain which contains all our widgets into the main window. */
765     gnome_app_set_contents(GNOME_APP(mainWindow), vBoxMain);
766     
767     /* DONT show the main window yet, due to a Gtk bug that causes it
768      * to not refresh the window when adding widgets after the window 
769      * has already been shown */
770     if (uid != euid)
771       setuid(euid);
772     for(i = 0; i < SIZE(ghack_chain); i++)
773         ghack_chain[i].handler =
774           signal(ghack_chain[i].signum, ghack_sig_handler);
775 }
776
777 void ghack_main_window_add_map_window(GtkWidget* win) 
778 {
779     GtkWidget *vBox;
780     
781     vBox= gtk_vbox_new (TRUE, 0);
782     gtk_box_pack_start (GTK_BOX (vBox), win, TRUE, TRUE, 2);
783     gtk_box_pack_start (GTK_BOX (vBoxMain), vBox, TRUE, TRUE, 2);
784     gtk_widget_show_all(vBox);
785     /* Ok, now show the main window -- now that we have added in 
786      * all the windows (relys on nethack displaying the map window last
787      * (This is an ugly kludge, BTW)
788      */
789     gtk_widget_show_all(mainWindow);
790 }
791
792 void
793 ghack_main_window_add_message_window(GtkWidget* win)
794 {
795     gtk_box_pack_start (GTK_BOX (hBoxFirstRow), win, TRUE, TRUE, 2);
796     gtk_widget_show_all(win);
797 }
798
799 void
800 ghack_main_window_add_status_window(GtkWidget* win)
801 {
802     gtk_box_pack_start (GTK_BOX (hBoxFirstRow), win, FALSE, TRUE, 2);
803     gtk_widget_show_all(win);
804 }
805
806 void
807 ghack_main_window_add_worn_window(GtkWidget* win)
808 {
809     gtk_box_pack_end (GTK_BOX (hBoxFirstRow), win, FALSE, TRUE, 2);
810     gtk_widget_show_all(win);
811 }
812
813 void
814 ghack_main_window_add_text_window(GtkWidget *win)
815 {
816   g_warning("Fixme!!! AddTextWindow is not yet implemented");
817 }
818
819 void
820 ghack_main_window_remove_window(GtkWidget *win)
821 {
822   g_warning("Fixme!!! RemoveWindow is not yet implemented");
823 }
824
825 void
826 ghack_main_window_update_inventory()
827 {
828 /* For now, do very little.  Eventually we may allow the inv. window
829      to stay active.  When we do this, we'll need to implement this...
830    g_warning("Fixme!!! updateInventory is not yet implemented");
831 */
832         gnome_display_nhwindow(WIN_WORN, FALSE);
833 }
834
835 GtkWidget*
836 ghack_get_main_window()
837 {
838       return( GTK_WIDGET(mainWindow) );
839 }