/* $Id: gtkint.c,v 1.6.2.1 2004/11/03 09:32:01 j_ali Exp $ */ /* GTK+ NetHack Copyright (c) Issei Numata 1999-2000 Copyright (c) Slash'EM Development Team 2001-2003 GTK+ NetHack may be freely redistributed. See license for details. */ /* * This module contains everything that is only needed for the internal * interface (ie., when linking the GTK interface with the game executable). */ #include #include #include "winGTK.h" #include "nhxdr.h" #include "proxycom.h" #include "prxyclnt.h" #include "wintype.h" #include "func_tab.h" #include "dlb.h" #ifdef SHORT_FILENAMES #include "patchlev.h" #else #include "patchlevel.h" #endif static void hook() { } #ifdef GTK_PROXY static void FDECL(GTK_proxy_init_nhwindows, (int *, char **)); static void NDECL(GTK_proxy_askname); static int NDECL(GTK_proxy_nhgetch); static void FDECL(GTK_proxy_raw_print, (const char *)); static void FDECL(GTK_proxy_raw_print_bold, (const char *)); /* Only the GTK_proxy_... functions are expected to be called. * Calling any other of these before GTK_proxy_init_nhwindows() * returns is likely to result in undefined behaviour. */ struct window_procs GTK_procs = { "gtk", 0, 0L, GTK_proxy_init_nhwindows, hook, /* player_selection */ GTK_proxy_askname, GTK_get_nh_event, GTK_exit_nhwindows, hook, /* suspend_nhwindows */ hook, /* resume_nhwindows */ GTK_create_nhwindow, hook, /* clear_nhwindow */ GTK_display_nhwindow, GTK_destroy_nhwindow, GTK_curs, GTK_putstr, #ifdef FILE_AREAS (void (*)(const char *, const char *, BOOLEAN_P))hook, /* display_file */ #else (void (*)(const char *, BOOLEAN_P))hook, /* display_file */ #endif GTK_start_menu, (void (*)(winid, int, const anything *, CHAR_P, CHAR_P, int, const char *, BOOLEAN_P))hook, /* add_menu */ GTK_end_menu, (int (*)())hook, /* select_menu */ genl_message_menu, GTK_update_inventory, GTK_mark_synch, GTK_wait_synch, #ifdef CLIPPING GTK_cliparound, #endif #ifdef POSITIONBAR hook, /* update_positionbar */ #endif (void (*)(winid, XCHAR_P, XCHAR_P, int))hook, /* print_glyph */ GTK_proxy_raw_print, GTK_proxy_raw_print_bold, GTK_proxy_nhgetch, GTK_nh_poskey, hook, /* nhbell */ GTK_doprev_message, (char (*)(const char *, const char *, CHAR_P))hook, /* yn_function */ hook, /* getlin */ GTK_get_ext_cmd, GTK_number_pad, GTK_delay_output, #ifdef CHANGE_COLOR hook, /* change_color */ #ifdef MAC hook, /* change_background */ hook, /* set_font_name */ #endif hook, /* get_color_string */ #endif hook, /* start_screen,*/ hook, /* end_screen,*/ genl_outrip, hook, /* preference_update,*/ }; static void GTK_proxy_askname(void) { strcpy(plname, "games"); } static int GTK_proxy_nhgetch(void) { int c; do { c = getchar(); } while(c == '\r'); return c; } static void GTK_proxy_raw_print(const char *str) { fputs(str, stderr); fputc('\n', stderr); (void) fflush(stderr); } static void GTK_proxy_raw_print_bold(const char *str) { fputs(str, stderr); fputc('\n', stderr); (void) fflush(stderr); } #ifndef WIN32 static int GTK_client_read(void *handle, void *buf, unsigned int len) { int nb; nb = read((int)handle, buf, len); return nb >= 0 ? nb : -1; } static int GTK_client_write(void *handle, void *buf, unsigned int len) { int nb; nb = write((int)handle, buf, len); return nb >= 0 ? nb : -1; } #endif static void GTK_proxy_init_nhwindows(int *argcp, char **argv) { int retval; #ifdef WIN32 /* Win32 has no concept of fork, so we simply execute ourselves */ char *s; iflags.window_inited = 1; proxy_svc_set_ext_procs(win_GTK_init, >K_ext_procs); s = g_find_program_in_path(argv[0]); retval = proxy_connect("file", s ? s : argv[0], argcp, argv); if (!retval) proxy_start_client_services(); exit(1); #else int to_game[2],from_game[2]; #ifdef UNIX uid_t uid; gid_t gid; #endif if (pipe(to_game) || pipe(from_game)) panic("%s: Can't create NhExt stream", argv[0]); iflags.window_inited = 1; if (fork()) { dup2(to_game[0],0); dup2(from_game[1],1); close(to_game[1]); close(from_game[0]); choose_windows("proxy"); if (strncmp(windowprocs.name, "proxy/", 6)) terminate(EXIT_SUCCESS); init_nhwindows(argcp, argv); } else { close(to_game[0]); close(from_game[1]); #ifdef UNIX /* * Drop all privileges. For non-Linux systems we just assume that * seteuid()/setuid() suffices. Add more cases as needed. */ gid = getgid(); uid = getuid(); #ifdef LINUX setresgid(gid, gid, gid); setresuid(uid, uid, uid); #else setegid(gid); setgid(gid); seteuid(uid); setuid(uid); #endif #endif proxy_svc_set_ext_procs(win_GTK_init, >K_ext_procs); retval = proxy_init_client_services(GTK_client_read, (void *)from_game[0], GTK_client_write, (void *)to_game[1]); if (!retval) proxy_start_client_services(); exit(1); } #endif /* WIN32 */ } #else /* GTK_PROXY */ static void FDECL(GTK_int_init_nhwindows, (int *, char **)); static void NDECL(GTK_int_player_selection); static void NDECL(GTK_int_askname); static void FDECL(GTK_int_clear_nhwindow, (winid)); #ifdef FILE_AREAS static void FDECL(GTK_int_display_file, (const char *, const char *, BOOLEAN_P)); #else static void FDECL(GTK_int_display_file, (const char *, BOOLEAN_P)); #endif static void FDECL(GTK_int_add_menu, (winid, int, const ANY_P *, CHAR_P, CHAR_P, int, const char *, BOOLEAN_P)); static int FDECL(GTK_int_select_menu, (winid, int, MENU_ITEM_P **)); static void FDECL(GTK_int_print_glyph, (winid, XCHAR_P, XCHAR_P, int)); static char FDECL(GTK_int_yn_function, (const char *, const char *, CHAR_P)); static void FDECL(GTK_int_outrip, (winid, int)); static void FDECL(GTK_int_getlin, (const char *, char *)); static void FDECL(GTK_int_preference_update, (const char *)); struct window_procs GTK_procs = { "gtk", /* If you want to change these you probably also want to change the * equivalent values in GTK_capv[]. */ WC_COLOR | WC_HILITE_PET | #if 0 WC_ASCII_MAP | WC_TILED_MAP | WC_SPLASH_SCREEN | WC_POPUP_DIALOG | WC_EIGHT_BIT_IN | #endif WC_PERM_INVENT, 0L, GTK_int_init_nhwindows, GTK_int_player_selection, GTK_int_askname, GTK_get_nh_event, GTK_exit_nhwindows, hook, /* suspend_nhwindows */ hook, /* resume_nhwindows */ GTK_create_nhwindow, GTK_int_clear_nhwindow, GTK_display_nhwindow, GTK_destroy_nhwindow, GTK_curs, GTK_putstr, GTK_int_display_file, GTK_start_menu, GTK_int_add_menu, GTK_end_menu, GTK_int_select_menu, genl_message_menu, GTK_update_inventory, GTK_mark_synch, GTK_wait_synch, #ifdef CLIPPING GTK_cliparound, #endif #ifdef POSITIONBAR hook, /* update_positionbar */ #endif GTK_int_print_glyph, GTK_raw_print, GTK_raw_print_bold, GTK_nhgetch, GTK_nh_poskey, hook, /* nhbell */ GTK_doprev_message, GTK_int_yn_function, GTK_int_getlin, GTK_get_ext_cmd, GTK_number_pad, GTK_delay_output, #ifdef CHANGE_COLOR hook, /* change_color */ #ifdef MAC hook, /* change_background */ hook, /* set_font_name */ #endif hook, /* get_color_string */ #endif hook, /* start_screen,*/ hook, /* end_screen,*/ #ifdef GRAPHIC_TOMBSTONE GTK_int_outrip, #else genl_outrip, #endif GTK_int_preference_update, }; static void GTK_int_init_nhwindows(int *argcp, char **argv) { char **capv; if (GTK_ext_init_nhwindows(argcp, argv, &capv)) iflags.window_inited = 1; } static void GTK_int_player_selection(void) { /* * The GTK interface does not provide a quit option within * player selection. */ (void)GTK_ext_player_selection(&flags.initrole, &flags.initrace, &flags.initgend, &flags.initalign); } static void GTK_int_askname() { char *name; name = GTK_ext_askname(); strcpy(plname, name); free(name); } static void GTK_int_clear_nhwindow(window) winid window; { GTK_ext_clear_nhwindow(window, ROWNO, COLNO, 1); } #ifdef FILE_AREAS static void GTK_int_display_file(farea, fname, complain) const char *farea, *fname; BOOLEAN_P complain; #else static void GTK_int_display_file(fname, complain) const char *fname; BOOLEAN_P complain; #endif { int fh; #ifdef FILE_AREAS fh = dlbh_fopen(farea, fname, "r"); #else fh = dlbh_fopen(fname, "r"); #endif if (fh < 0) { if (complain) pline("Can't open %s.", fname); return; } GTK_ext_display_file(fh); dlbh_fclose(fh); } static void GTK_int_add_menu(window, glyph, identifier, ch, gch, attr, str, preselected) winid window; int glyph; const anything *identifier; CHAR_P ch, gch; int attr; const char *str; BOOLEAN_P preselected; { int mapping = mapid_map_identifier(window, identifier); GTK_ext_add_menu(window, glyph, mapping, ch, gch, attr, str, preselected); } int GTK_int_select_menu(window, how, menu_list) winid window; int how; menu_item **menu_list; { int i, n, retval; struct proxy_mi *selected; retval = GTK_ext_select_menu(window, how, &selected); n = retval <= 0 ? 0 : retval; *menu_list = (menu_item *) alloc(n * sizeof(menu_item)); for(i = 0; i < n; i++) { mapid_unmap_identifier(window, selected[i].item, &(*menu_list)[i].item); (*menu_list)[i].count = selected[i].count; } if (n) free(selected); return retval; } static void GTK_int_print_glyph(window, x, y, glyph) winid window; xchar x, y; int glyph; { GTK_ext_print_glyph(window, x, y, glyph); } static char GTK_int_yn_function(query, resp, def) const char *query, *resp; char def; { char ret; int count; ret = GTK_ext_yn_function(query, resp ? resp : "", def, &count); if (ret == '#') yn_number = count; return ret; } static void GTK_int_outrip(winid id, int how) { if (!GTK_ext_outrip(id, get_killer_string(how))) genl_outrip(id, how); } static void GTK_int_getlin(const char *query, char *ret) { char *line; line = GTK_ext_getlin(query); strcpy(ret, line); free(line); } static void GTK_int_preference_update(const char *optnam) { GTK_ext_preference_update(optnam, get_option(optnam)); } #endif /* GTK_PROXY */