/*
 *  $Id: gtk_main.c,v 1.1.1.1 1999/04/26 22:44:54 route Exp $
 *
 *  Firewalk
 *  gtk code
 *  gtk_main.c - gtk interface routines
 *
 *  Copyright (c) 1999 Mike D. Schiffman <mike@infonexus.com>
 *  Copyright (c) 1998 Mike D. Schiffman <mds@es2.net>
 *  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 */

#if (HAVE_CONFIG_H)
#include "./config.h"
#endif
#include "./gtk_main.h"
#include "./gtk_util.h"
#include "./gtk_cb.h"
#include "./gtk_pack.h"
#include "./main.h"
#include "./packet.h"
#include "./gtk_itemfactory.h"
#include "./firewalk.h"
#include "./version.h"

/*
 *  This code is heavily commented for the benefit of the programmer who
 *  wants to learn GTK.  Note that there is no error checking done on any
 *  GTK calls.  None of the GTK code I've looked at (tutorial example code,
 *  GNU info documentation sample code, the example code that came with the
 *  library, and finally, several GTK-based applications) check for errors.
 *  I'm not sure why people don't check the return values of gtk_* calls,
 *  but they don't.  So I don't.
 */

void
gtk_init_interface(int *argc, char ***argv)
{
    GtkWidget *main_window, *packing_grid, *button_box_frame;
    GtkWidget *text_window_hbox;
    GtkWidget *menu_bar, *quit_button, *button_box, *cp_button, *firewalk_button;
    GtkWidget *text_window_scrollbar, *d_label, *g_label;
    GtkTooltips *g_addr_tt, *d_addr_tt;
    GtkTooltips *quit_button_tt, *firewalk_button_tt, *cp_button_tt;
    GtkAdjustment *adj;

    /*
     *  Initialize the GTK library.  Every GTK application must do this.
     */
    gtk_init(argc, argv);

    /*
     *  Create the main window and set its name.
     */
    main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_widget_set_name(main_window, "firewalk main window");

    /*
     *  Set the main window title and size.
     */
    gtk_window_set_title(GTK_WINDOW(main_window), "Firewalk");
    gtk_widget_set_usize(GTK_WIDGET(main_window), WIDTH, HEIGHT);

    /*
     *  Set window policies.  Allow shrinking and growing but not
     *  autoshrinking.
     */
    gtk_window_set_policy(GTK_WINDOW(main_window), TRUE, TRUE, TRUE);

    /*
     *  Setup the signal callback for the delete_event event and the destroy
     *  event for our main window.
     */
    gtk_signal_connect(GTK_OBJECT(main_window), "delete_event",
        GTK_SIGNAL_FUNC(gtk_quit_main_cb), NULL);
    gtk_signal_connect(GTK_OBJECT(main_window), "destroy",
        GTK_SIGNAL_FUNC(gtk_quit_main_cb), NULL);

    /*
     *  The packing grid is how we arrange widgets on the screen.
     */
    packing_grid = gtk_table_new(50, 50, FALSE);

    /*
     *  Set the border width for the grid.
     */
    gtk_container_border_width(GTK_CONTAINER(packing_grid), BORDER_WIDTH_0);

    /*
     *  Pack the grid into the main window.  This is the only widget
     *  we will be packing into the main window so we can easily pack it
     *  with gtk_container_add.
     */
    gtk_container_add(GTK_CONTAINER(main_window), packing_grid);

    /*
     *  Initialize the itemfactory.  This is how GTK does menubars.  Pack
     *  it into the grid.
     */
    gtk_init_itemfactory(main_window, &menu_bar);
    gtk_table_attach(GTK_TABLE(packing_grid),
        menu_bar,           /* widget we are packing */
        0,                  /* left grid coordinate */
        49,                 /* rite grid coordinate */
        0,                  /* top grid coordinate */
        1,                  /* bottom grid coordinate */
        GTK_FILL|GTK_EXPAND,/* fill and expand on the X axis */
        0,                  /* but not the Y */
        0,                  /* no X padding */
        0);                 /* no Y padding */

    /*
     *  Text window and associated widgetry.  We need an hbox so we can pack a
     *  scrollbar rite next to the text window.
     */
    gp->text_window = gtk_text_new(NULL, NULL);
    gp->font = gdk_font_load("-misc-fixed-medium-r-*-*-*-140-*-*-*-*-*-*");
    text_window_hbox = gtk_hbox_new(FALSE, 0);
    text_window_scrollbar = 
        gtk_vscrollbar_new(GTK_TEXT((gp->text_window))->vadj);
    gtk_box_pack_start(GTK_BOX(text_window_hbox), gp->text_window, TRUE, TRUE, 
        0);
    gtk_box_pack_start(GTK_BOX(text_window_hbox), text_window_scrollbar,
        FALSE, FALSE, 0);
    gtk_table_attach(GTK_TABLE(packing_grid),
        text_window_hbox,   /* widget we are packing */
        0,                  /* left grid coordinate */
        49,                 /* rite grid coordinate */
        1,                  /* top grid coordinate */
        50,                 /* bottom grid coordinate */
        GTK_FILL|GTK_EXPAND,/* fill and expand on the X axis */
        GTK_FILL|GTK_EXPAND,/* fill and expand on the Y axis */
        0,                  /* no X padding */
        0);                 /* no Y padding */

    /*
     *  Hi there.
     */
    gtk_text_insert(GTK_TEXT(gp->text_window),
        gp->font,
        NULL,
        NULL,
        "Welcome to firewalk/GTK.\n",
        -1);

    /*
     *  Progress bar.
     */
    adj = (GtkAdjustment *)gtk_adjustment_new(0, 1, fp->ports_total, 0, 0, 0);
    gp->p_bar = gtk_progress_bar_new_with_adjustment(adj);
    gtk_progress_set_format_string(GTK_PROGRESS(gp->p_bar), "%p%%");

    gtk_table_attach(GTK_TABLE(packing_grid),
        gp->p_bar,          /* widget we are packing */
        0,                  /* left grid coordinate */
        49,                 /* rite grid coordinate */
        50,                 /* top grid coordinate */
        51,                 /* bottom grid coordinate */
        GTK_FILL|GTK_EXPAND,/* fill and expand on the X axis */
        0,
        0,                  /* no X padding */
        0);                 /* no Y padding */

    /*
     *  Address entry widgets.
     */
    gp->g_entry = gtk_entry_new_with_max_length(ENTRY_SIZE);
    gp->d_entry = gtk_entry_new_with_max_length(ENTRY_SIZE);
    g_label = gtk_label_new("gateway host");
    d_label = gtk_label_new("destination host");

    g_addr_tt = gtk_tooltips_new();
    gtk_tooltips_set_tip(g_addr_tt, gp->g_entry, "Host to scan through", NULL);

    d_addr_tt = gtk_tooltips_new();
    gtk_tooltips_set_tip(d_addr_tt, gp->d_entry, "Metric host", NULL);

    /*
     *  If we have command line supplied host arguments, display them now.
     */
    if (fp->gateway)
    {
        gtk_entry_set_text(GTK_ENTRY(gp->g_entry),
            libnet_host_lookup(fp->gateway, 0));
    }
    else
    {
        gtk_text_insert(GTK_TEXT(gp->text_window),
            gp->font,
            NULL,
            NULL,
            "Please enter a gateway host.\n",
            -1);
    }
    if (fp->destination)
    {
        gtk_entry_set_text(GTK_ENTRY(gp->d_entry),
            libnet_host_lookup(fp->destination, 0));
    }
    else
    {
        gtk_text_insert(GTK_TEXT(gp->text_window),
            gp->font,
            NULL,
            NULL,
            "Please enter a destination host.\n",
            -1);
    }

    gtk_table_attach(GTK_TABLE(packing_grid),
        g_label,
        1,                  /* left grid coordinate */
        2,                  /* rite grid coordinate */
        50,                 /* top grid coordinate */
        51,                 /* bottom grid coordinate */
        0,
        0,
        122,                /* some X padding */
        2);                 /* no Y padding */
    gtk_table_attach(GTK_TABLE(packing_grid),
        d_label,
        2,                  /* left grid coordinate */
        3,                  /* rite grid coordinate */
        50,                 /* top grid coordinate */
        51,                 /* bottom grid coordinate */
        0,
        0,
        0,                  /* no X padding */
        2);                 /* no Y padding */

    gtk_table_attach(GTK_TABLE(packing_grid),
        gp->g_entry,
        1,                  /* left grid coordinate */
        2,                  /* rite grid coordinate */
        51,                 /* top grid coordinate */
        52,                 /* bottom grid coordinate */
        0,
        0,
        122,                /* some X padding */
        2);                 /* no Y padding */
    gtk_table_attach(GTK_TABLE(packing_grid),
        gp->d_entry,
        2,                  /* left grid coordinate */
        3,                  /* rite grid coordinate */
        51,                 /* top grid coordinate */
        52,                 /* bottom grid coordinate */
        0,
        0,
        0,                  /* no X padding */
        2);                 /* no Y padding */

    /*
     *  Initialize our button box and button box frame and then pack them 
     *  into the grid.
     */
    button_box = gtk_hbutton_box_new();
    gtk_button_box_set_layout(GTK_BUTTON_BOX(button_box), GTK_BUTTONBOX_END);
    button_box_frame = gtk_frame_new("What is your pleasure, sir?");
    gtk_widget_set_usize(GTK_WIDGET(button_box_frame), 400, 50);

    gtk_table_attach(GTK_TABLE(packing_grid),
        button_box,         /* widget we are packing */
        1,                  /* left grid coordinate */
        30,                 /* rite grid coordinate */
        54,                 /* top grid coordinate */
        55,                 /* bottom grid coordinate */
        0,
        0,
        145,                /* no X padding */
        2);                 /* no Y padding */
    gtk_table_attach(GTK_TABLE(packing_grid),
        button_box_frame,   /* widget we are packing */
        1,                  /* left grid coordinate */
        30,                 /* rite grid coordinate */
        53,                 /* top grid coordinate */
        55,                 /* bottom grid coordinate */
        0,
        0,
        145,                /* some X padding */
        2);                 /* no Y padding */

    /*
     *  Initialize our firewalk button and associated tooltip.
     */
    firewalk_button = gtk_button_new_with_label("Firewalk");
    gtk_signal_connect_object(GTK_OBJECT(firewalk_button), "clicked",
        GTK_SIGNAL_FUNC(gtk_firewalk_cb), GTK_OBJECT(main_window));
    gtk_box_pack_start(GTK_BOX(button_box), firewalk_button, TRUE, TRUE, 0);
    GTK_WIDGET_SET_FLAGS(firewalk_button, GTK_CAN_DEFAULT);
    gtk_widget_grab_default(firewalk_button);
    firewalk_button_tt = gtk_tooltips_new();
    gtk_tooltips_set_tip(firewalk_button_tt, firewalk_button,
        "Fire, walk with me where?", NULL);

    /*
     *  Initialize our control panel button and associated tooltip.
     */
    cp_button = gtk_button_new_with_label("Control Panel");
    gtk_signal_connect_object(GTK_OBJECT(cp_button), "clicked",
        GTK_SIGNAL_FUNC(gtk_cp_cb), GTK_OBJECT(main_window));
    gtk_box_pack_start(GTK_BOX(button_box), cp_button, TRUE, TRUE, 0);
    GTK_WIDGET_SET_FLAGS(cp_button, GTK_CAN_DEFAULT);
    gtk_widget_grab_default(cp_button);
    cp_button_tt = gtk_tooltips_new();
    gtk_tooltips_set_tip(cp_button_tt, cp_button, "You are in control!",
         NULL);

    /*
     *  Initialize our quit button and associated tooltip.
     */
    quit_button = gtk_button_new_with_label("Quit");
    gtk_signal_connect_object(GTK_OBJECT(quit_button), "clicked",
        GTK_SIGNAL_FUNC(gtk_quit_main_cb), GTK_OBJECT(main_window));
    gtk_box_pack_start(GTK_BOX(button_box), quit_button, TRUE, TRUE, 0);
    GTK_WIDGET_SET_FLAGS(quit_button, GTK_CAN_DEFAULT);
    gtk_widget_grab_default(quit_button);
    quit_button_tt = gtk_tooltips_new();
    gtk_tooltips_set_tip(quit_button_tt, quit_button, "Beat it kid.", NULL);

    /*
     *  Rather than individual calls to gtk_widget_show, we can make one
     *  call here and display all the widgets packed into the specified widget.
     */
    gtk_widget_show_all(main_window);
}


void
gtk_init_itemfactory(GtkWidget *window, GtkWidget **menu_bar)
{
    int num_menu_items;
    GtkItemFactory *item_factory;
    GtkAccelGroup *accel_group;

    accel_group = gtk_accel_group_new();

    /*
     *  This function initializes the item factory.
     *  Param 1: The type of menu - can be GTK_TYPE_MENU_BAR, GTK_TYPE_MENU,
     *      or GTK_TYPE_OPTION_MENU.
     *  Param 2: The path of the menu.
     *  Param 3: A pointer to a gtk_accel_group.  The item factory sets up the
     *      accelerator table while generating menus.
     */
    item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>",
        accel_group);

    /*
     *  This function generates the menu items. Pass the item factory, the
     *  number of items in the array, the array itself, and any callback data
     *  for the the menu items.
     */
    num_menu_items = sizeof(menu_items) / sizeof(menu_items[0]);
    gtk_item_factory_create_items(item_factory, num_menu_items, menu_items,
        NULL);

    /*
     *  Attach the new accelerator group to the window.
     */
    gtk_accel_group_attach(accel_group, GTK_OBJECT(window));

    /*
     *  Finally, return the actual menu bar created by the item factory.
     */
    if (menu_bar)
    {
        *menu_bar = gtk_item_factory_get_widget(item_factory, "<main>");
    }
}


int
gtk_init_gtkpack(struct gtkpack **gp)
{
    *gp = (struct gtkpack *)malloc(sizeof(struct gtkpack));
    if (!(*gp))
    {
        perror("init_gtkpack: malloc");
        return (-1);
    }
    (*gp)->g_entry      = NULL;
    (*gp)->d_entry      = NULL;
    (*gp)->text_window  = NULL;
    (*gp)->font         = NULL;
    (*gp)->i_port_sb    = NULL;
    (*gp)->s_port_sb    = NULL;
    (*gp)->ttl_sb       = NULL;
    (*gp)->wp_sb        = NULL;
    (*gp)->rp_sb        = NULL;
    (*gp)->rb           = NULL;
    (*gp)->dns_cb       = NULL;
    (*gp)->quiet_cb     = NULL;
    (*gp)->file_cb      = NULL;
    (*gp)->plist_entry  = NULL;
}

void
gtk_about_firewalk()
{
    gtk_text_box(FSD_TYPE_INFO, BANNER "version %s", version);
}


/* EOF */
