/* GemVt - GNU Emulator of a Virtual Terminal * Copyright (C) 1997 Tim Janik * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config.h" #include "gvtvt.h" #include "gvtconf.h" #include "gemvt.xpm" #include #include #include #include #include #ifdef HAVE_GNOME # include #endif HAVE_GNOME #ifdef HAVE_LIBGLE # include #endif /* HAVE_LIBGLE */ /* --- typedefs --- */ enum { GVT_VOIDLINE, GVT_ONLINE, GVT_OFFLINE }; /* --- prototypes --- */ static RETSIGTYPE gvt_signal_handler (int sig_num); static gint gvt_tty_key_press (GtkTty *tty, const gchar *char_code, guint length, guint keyval, guint key_state, gpointer data); static gint gvt_tty_button_press (GtkWidget *widget, GdkEventButton *event); static void gtk_menu_position_func (GtkMenu *menu, gint *x, gint *y, gpointer user_data); static void gvt_menu_adjust (GtkMenu *menu); static void gvt_menus_setup (void); static void gvt_menus_shutdown (void); /* --- static variables --- */ static GvtColorEntry linux_ct[GTK_TERM_MAX_COLORS] = { /* back fore dim bold */ { 0x000000, 0x000000, 0x000000, 0x000000 }, /* black */ { 0xd00000, 0xd00000, 0x880000, 0xff0000 }, /* red */ { 0x00d000, 0x00d000, 0x008800, 0x00ff00 }, /* green */ { 0xd0d000, 0xd0d000, 0x888800, 0xffff00 }, /* orange */ { 0x0000d0, 0x0000d0, 0x000088, 0x0000ff }, /* blue */ { 0xd000d0, 0xd000d0, 0x880088, 0xff00ff }, /* pink */ { 0x00d0d0, 0x00d0d0, 0x008888, 0x00ffff }, /* cyan */ { 0xd0d0d0, 0xd0d0d0, 0x888888, 0xffffff }, /* white */ }; static GtkMenu *menu_1 = NULL; static GtkMenu *menu_2 = NULL; static GtkMenu *menu_3 = NULL; static GtkTty *menu_tty; static gint menu_pos_x, menu_pos_y; static GvtConfig config = { TRUE /* have_status_bar */, FALSE /* prefix_dash */, NULL /* strings */, }; /* --- main() --- */ int main (int argc, char *argv[]) { gchar *home_dir; gchar *rc_file; guchar *string; GtkObject *vt; guint id; gint exit_status; guint i; prg_name = g_strdup (argv[0]); /* parse arguments */ exit_status = gvt_config_args (&config, stderr, argc, argv); if (exit_status > -129) return exit_status; /* Gtk+/GNOME/GLE initialization */ #ifdef HAVE_GNOME gnome_init("gemvt", NULL, argc, argv, 0, NULL); #else /* !HAVE_GNOME */ gtk_init (&argc, &argv); #endif /* !HAVE_GNOME */ #ifdef HAVE_LIBGLE gle_init (&argc, &argv); #endif /* HAVE_LIBGLE */ /* parse ~/.gtkrc, (this file also ommitted by the gnome_init stuff */ home_dir = getenv ("HOME"); if (!home_dir) /* fatal! */ home_dir = "."; string = "gtkrc"; rc_file = g_new (gchar, strlen (home_dir) + 2 + strlen (string) + 1); *rc_file = 0; strcat (rc_file, home_dir); strcat (rc_file, "/."); strcat (rc_file, string); /* printf("%s\n", rc_file); */ gtk_rc_parse (rc_file); g_free (rc_file); string = strrchr (prg_name, '/'); if (string) string++; else string = prg_name; rc_file = g_new (gchar, strlen (home_dir) + 2 + strlen (string) + 2 + 1); *rc_file = 0; strcat (rc_file, home_dir); strcat (rc_file, "/."); strcat (rc_file, string); strcat (rc_file, "rc"); /* parse ~/.rc */ /* printf("%s\n", rc_file); */ /* FIXME: invoke rc-parser here */ g_free (rc_file); /* catch system signals */ gvt_signal_handler (0); /* fire up default vt (test code) */ string = "Hi, this is GemVt bothering you ;)\n\r" "Enter `-bash' or something the like and\n\r" "Have Fun!!!\n\r"; vt = gvt_vt_new (GVT_VT_WINDOW, NULL); for (i = 0; i < GTK_TERM_MAX_COLORS; i++) gvt_vt_set_color (GVT_VT (vt), i, &linux_ct[i]); gvt_vt_execute (GVT_VT (vt), "-/bin/bash"); gvt_menus_setup (); /* gtk's main loop */ gtk_main (); gvt_menus_shutdown (); /* exit program */ return 0; } RETSIGTYPE gvt_signal_handler (int sig_num) { static gboolean in_call = FALSE; if (in_call) { fprintf (stderr, "\naborting on another signal: `%s'\n", g_strsignal (sig_num)); fflush (stderr); gtk_exit (-1); } else in_call = TRUE; signal (SIGINT, gvt_signal_handler); signal (SIGTRAP, gvt_signal_handler); signal (SIGABRT, gvt_signal_handler); signal (SIGBUS, gvt_signal_handler); signal (SIGSEGV, gvt_signal_handler); signal (SIGPIPE, gvt_signal_handler); /* signal (SIGTERM, gvt_signal_handler); */ if (sig_num > 0) { fprintf (stderr, "%s: (pid: %d) caught signal: `%s'\n", prg_name, getpid (), g_strsignal (sig_num)); fflush (stderr); g_on_error_query (prg_name); } in_call = FALSE; } static gint gvt_tty_key_press (GtkTty *tty, const gchar *char_code, guint length, guint keyval, guint key_state, gpointer data) { GtkWidget *status_bar; register guint id; /* return wether we handled the key press: * FALSE) let GtkTty handle the keypress, * TRUE) we do something like gtk_tty_put_in (tty, char_code, length) on * our own. */ status_bar = gtk_object_get_data (GTK_OBJECT (tty), "status-bar"); id = (gint) gtk_object_get_data (GTK_OBJECT (tty), "key_press_hid"); if (id) { gtk_signal_disconnect (GTK_OBJECT (tty), id); gtk_object_set_data (GTK_OBJECT (tty), "key_press_hid", (gpointer) 0); } return FALSE; } static gint gvt_tty_button_press (GtkWidget *widget, GdkEventButton *event) { GtkTty *tty; /* 1) return wether we handled the event * 2) if we handled it we need to prevent gtktty region selection, * therefor we stop the emission of the signal */ tty = GTK_TTY (widget); if ((event->state & (GDK_SHIFT_MASK | GDK_LOCK_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK)) == GDK_CONTROL_MASK) { switch (event->button) { case 1: gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "button_press_event"); gdk_window_get_pointer (NULL, &menu_pos_x, &menu_pos_y, NULL); menu_tty = tty; gvt_menu_adjust (menu_1); gtk_menu_popup (menu_1, NULL, NULL, gtk_menu_position_func, NULL, 1, event->time); return TRUE; } } return FALSE; } static void gtk_menu_position_func (GtkMenu *menu, gint *x, gint *y, gpointer user_data) { *x = menu_pos_x; *y = menu_pos_y; } static void gvt_menu_toggle_status_bar (GtkWidget *widget, gpointer data) { GtkWidget *status_bar; status_bar = gtk_object_get_data (GTK_OBJECT (menu_tty), "status-bar"); g_assert (status_bar != NULL); if (GTK_WIDGET_VISIBLE (status_bar)) gtk_widget_hide (status_bar); else gtk_widget_show (status_bar); } static void gvt_menu_tty_redraw (GtkWidget *widget, gpointer data) { gtk_widget_draw (GTK_WIDGET (menu_tty), NULL); } static void gvt_menu_send_signal (GtkWidget *widget, gpointer data) { g_assert (menu_tty != NULL); g_assert (menu_tty->pid > 0); kill (menu_tty->pid, (gint) data); } static void gvt_menu_adjust (GtkMenu *menu) { GList *list, *free_list; g_assert (menu != NULL); list = free_list = gtk_container_children (GTK_CONTAINER (menu)); while (list) { gint ac; ac = (gint) gtk_object_get_data (GTK_OBJECT (list->data), "activate"); switch (ac) { case GVT_ONLINE: gtk_widget_set_sensitive (GTK_WIDGET (list->data), menu_tty->pid > 0); break; case GVT_OFFLINE: gtk_widget_set_sensitive (GTK_WIDGET (list->data), menu_tty->pid == 0); break; } list = list->next; } g_list_free (free_list); } static void gvt_menus_setup (void) { GtkWidget *menu; if (!menu_1) { GtkWidget *item; menu = gtk_widget_new (gtk_menu_get_type (), "GtkObject::signal::destroy", gtk_widget_destroyed, &menu_1, NULL); menu_1 = GTK_MENU (menu); item = gtk_menu_item_new_with_label ("Main Options"); gtk_widget_set_sensitive (item, FALSE); gtk_widget_show (item); gtk_menu_append (GTK_MENU (menu), item); item = gtk_menu_item_new (); gtk_widget_set_sensitive (item, FALSE); gtk_widget_show (item); gtk_menu_append (GTK_MENU (menu), item); item = gtk_menu_item_new_with_label ("Redraw"); gtk_signal_connect(GTK_OBJECT (item), "activate", GTK_SIGNAL_FUNC (gvt_menu_tty_redraw), NULL); gtk_widget_show (item); gtk_menu_append (GTK_MENU (menu), item); item = gtk_menu_item_new_with_label ("Toggle Status Bar"); gtk_signal_connect(GTK_OBJECT (item), "activate", GTK_SIGNAL_FUNC (gvt_menu_toggle_status_bar), NULL); gtk_widget_show (item); gtk_menu_append (GTK_MENU (menu), item); item = gtk_menu_item_new (); gtk_widget_set_sensitive (item, FALSE); gtk_widget_show (item); gtk_menu_append (GTK_MENU (menu), item); item = gtk_menu_item_new_with_label ("SIGSTOP"); gtk_object_set_data (GTK_OBJECT (item), "activate", (gpointer) GVT_ONLINE); gtk_signal_connect(GTK_OBJECT (item), "activate", GTK_SIGNAL_FUNC (gvt_menu_send_signal), (gpointer) SIGSTOP); gtk_widget_show (item); gtk_menu_append (GTK_MENU (menu), item); item = gtk_menu_item_new_with_label ("SIGCONT"); gtk_object_set_data (GTK_OBJECT (item), "activate", (gpointer) GVT_ONLINE); gtk_signal_connect(GTK_OBJECT (item), "activate", GTK_SIGNAL_FUNC (gvt_menu_send_signal), (gpointer) SIGCONT); gtk_widget_show (item); gtk_menu_append (GTK_MENU (menu), item); item = gtk_menu_item_new_with_label ("SIGINT"); gtk_object_set_data (GTK_OBJECT (item), "activate", (gpointer) GVT_ONLINE); gtk_signal_connect(GTK_OBJECT (item), "activate", GTK_SIGNAL_FUNC (gvt_menu_send_signal), (gpointer) SIGINT); gtk_widget_show (item); gtk_menu_append (GTK_MENU (menu), item); item = gtk_menu_item_new_with_label ("SIGHUP"); gtk_object_set_data (GTK_OBJECT (item), "activate", (gpointer) GVT_ONLINE); gtk_signal_connect(GTK_OBJECT (item), "activate", GTK_SIGNAL_FUNC (gvt_menu_send_signal), (gpointer) SIGHUP); gtk_widget_show (item); gtk_menu_append (GTK_MENU (menu), item); item = gtk_menu_item_new_with_label ("SIGTERM"); gtk_object_set_data (GTK_OBJECT (item), "activate", (gpointer) GVT_ONLINE); gtk_signal_connect(GTK_OBJECT (item), "activate", GTK_SIGNAL_FUNC (gvt_menu_send_signal), (gpointer) SIGTERM); gtk_widget_show (item); gtk_menu_append (GTK_MENU (menu), item); item = gtk_menu_item_new_with_label ("SIGKILL"); gtk_object_set_data (GTK_OBJECT (item), "activate", (gpointer) GVT_ONLINE); gtk_signal_connect(GTK_OBJECT (item), "activate", GTK_SIGNAL_FUNC (gvt_menu_send_signal), (gpointer) SIGKILL); gtk_widget_show (item); gtk_menu_append (GTK_MENU (menu), item); item = gtk_menu_item_new (); gtk_widget_set_sensitive (item, FALSE); gtk_widget_show (item); gtk_menu_append (GTK_MENU (menu), item); item = gtk_menu_item_new_with_label ("Exit"); gtk_signal_connect(GTK_OBJECT (item), "activate", GTK_SIGNAL_FUNC (gtk_main_quit), NULL); gtk_widget_show (item); gtk_menu_append (GTK_MENU (menu), item); } if (!menu_2) { menu = gtk_widget_new (gtk_menu_get_type (), "GtkObject::signal::destroy", gtk_widget_destroyed, &menu_2, NULL); menu_2 = GTK_MENU (menu); } if (!menu_3) { menu = gtk_widget_new (gtk_menu_get_type (), "GtkObject::signal::destroy", gtk_widget_destroyed, &menu_3, NULL); menu_3 = GTK_MENU (menu); } } static void gvt_menus_shutdown (void) { if (menu_1) gtk_object_sink (GTK_OBJECT (menu_1)); if (menu_2) gtk_object_sink (GTK_OBJECT (menu_2)); if (menu_3) gtk_object_sink (GTK_OBJECT (menu_3)); }