Annotation of embedaddon/mtr/gtk.c, revision 1.1.1.2

1.1       misho       1: /*
                      2:     mtr  --  a network diagnostic tool
                      3:     Copyright (C) 1997,1998  Matt Kimball
                      4:     Changes/additions Copyright (C) 1998 R.E.Wolff@BitWizard.nl
                      5: 
                      6:     This program is free software; you can redistribute it and/or modify
                      7:     it under the terms of the GNU General Public License version 2 as 
                      8:     published by the Free Software Foundation.
                      9: 
                     10:     This program is distributed in the hope that it will be useful,
                     11:     but WITHOUT ANY WARRANTY; without even the implied warranty of
                     12:     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     13:     GNU General Public License for more details.
                     14: 
                     15:     You should have received a copy of the GNU General Public License
                     16:     along with this program; if not, write to the Free Software
                     17:     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
                     18: */
                     19: 
1.1.1.2 ! misho      20: #include "config.h"
1.1       misho      21: 
                     22: #include <stdio.h>
                     23: #include <stdlib.h>
                     24: #include <unistd.h>
                     25: #include <sys/time.h>
                     26: #include <sys/types.h>
                     27: 
                     28: #ifndef NO_GTK
                     29: #include <string.h>
                     30: #include <sys/types.h>
                     31: #include <gtk/gtk.h>
                     32: 
                     33: #include "mtr.h"
                     34: #include "net.h"
                     35: #include "dns.h"
                     36: #include "mtr-gtk.h"
                     37: #include "version.h"
                     38: 
                     39: #include "img/mtr_icon.xpm"
                     40: #endif
                     41: 
                     42: gint gtk_ping(gpointer data);
                     43: gint Copy_activate(GtkWidget *widget, gpointer data);
                     44: gint NewDestination_activate(GtkWidget *widget, gpointer data);
                     45: gboolean ReportTreeView_clicked(GtkWidget *Tree, GdkEventButton *event);
                     46: gchar* getSelectedHost(GtkTreePath *path);
                     47: 
                     48: 
                     49: 
                     50: extern char *Hostname;
                     51: extern float WaitTime;
                     52: extern int af;
                     53: static int tag;
                     54: static GtkWidget *Pause_Button;
                     55: static GtkWidget *Entry;
                     56: static GtkWidget *main_window;
                     57: 
                     58: void gtk_add_ping_timeout (void)
                     59: {
                     60:   int dt;
                     61: 
                     62:   dt = calc_deltatime (WaitTime);
                     63:   tag = g_timeout_add(dt / 1000, gtk_ping, NULL);
                     64: }
                     65: 
                     66: 
                     67: void gtk_do_init(int *argc, char ***argv) 
                     68: {
                     69:   static int done = 0;
                     70: 
                     71:   if(!done) {
                     72:     gtk_init(argc, argv);
                     73: 
                     74:     done = 1;
                     75:   }
                     76: }
                     77: 
                     78: 
                     79: int gtk_detect(UNUSED int *argc, UNUSED char ***argv) 
                     80: {
                     81:   if(getenv("DISPLAY") != NULL) {
                     82:     /* If we do this here, gtk_init exits on an error. This happens
                     83:        BEFORE the user has had a chance to tell us not to use the 
                     84:        display... */
                     85:     return TRUE;
                     86:   } else {
                     87:     return FALSE;
                     88:   }
                     89: }
                     90: 
                     91: 
                     92: gint Window_destroy(UNUSED GtkWidget *Window, UNUSED gpointer data) 
                     93: {
                     94:   gtk_main_quit();
                     95: 
                     96:   return FALSE;
                     97: }
                     98: 
                     99: 
                    100: gint Restart_clicked(UNUSED GtkWidget *Button, UNUSED gpointer data) 
                    101: {
                    102:   net_reset();
                    103:   gtk_redraw();
                    104: 
                    105:   return FALSE;
                    106: }
                    107: 
                    108: 
                    109: gint Pause_clicked(UNUSED GtkWidget *Button, UNUSED gpointer data) 
                    110: {
                    111:   static int paused = 0;
                    112: 
                    113:   if (paused) {
                    114:     gtk_add_ping_timeout ();
                    115:   } else {
                    116:     g_source_remove (tag);
                    117:   }
                    118:   paused = ! paused;
                    119:   gtk_redraw();
                    120: 
                    121:   return FALSE;
                    122: }
                    123: 
                    124: gint About_clicked(UNUSED GtkWidget *Button, UNUSED gpointer data) 
                    125: {
                    126:   gchar *authors[] = {
                    127:         "Matt Kimball <mkimball@xmission.com>",
                    128:         "Roger Wolff <R.E.Wolff@BitWizard.nl>",
                    129:         "Bohdan Vlasyuk <bohdan@cec.vstu.vinnica.ua>",
                    130:         "Evgeniy Tretyak <evtr@ukr.net>",
                    131:         "John Thacker <thacker@math.cornell.edu>",
                    132:         "Juha Takala",
                    133:         "David Sward <sward@clark.net>",
                    134:         "David Stone <stone@AsIf.com>",
                    135:         "Andrew Stesin",
                    136:         "Greg Stark <gsstark@mit.edu>",
                    137:         "Robert Sparks <rjsparks@nostrum.com>",
                    138:         "Mike Simons <msimons@moria.simons-clan.com>",
                    139:         "Aaron Scarisbrick,",
                    140:         "Craig Milo Rogers <Rogers@ISI.EDU>",
                    141:         "Antonio Querubin <tony@aloha.net>",
                    142:         "Russell Nelson <rn-mtr@crynwr.com>",
                    143:         "Davin Milun <milun@acm.org>",
                    144:         "Josh Martin <jmartin@columbiaservices.net>",
                    145:         "Alexander V. Lukyanov <lav@yars.free.net>",
                    146:         "Charles Levert <charles@comm.polymtl.ca> ",
                    147:         "Bertrand Leconte <B.Leconte@mail.dotcom.fr>",
                    148:         "Anand Kumria",
                    149:         "Olav Kvittem <Olav.Kvittem@uninett.no>",
                    150:         "Adam Kramer <l3zqc@qcunix1.acc.qc.edu> ",
                    151:         "Philip Kizer <pckizer@nostrum.com>",
                    152:         "Simon Kirby",
                    153:         "Christophe Kalt",
                    154:         "Steve Kann <stevek@spheara.horizonlive.com>",
                    155:         "Brett Johnson <brett@jdacareers.com>",
                    156:         "Roland Illig <roland.illig@gmx.de>",
                    157:         "Damian Gryski <dgryski@uwaterloo.ca>",
                    158:         "Rob Foehl <rwf@loonybin.net>",
                    159:         "Mircea Damian",
                    160:         "Cougar <cougar@random.ee>",
                    161:         "Travis Cross <tc@traviscross.com>",
                    162:         "Brian Casey",
                    163:         "Andrew Brown <atatat@atatdot.net>",
                    164:         "Bill Bogstad <bogstad@pobox.com> ",
                    165:         "Marc Bejarano <marc.bejarano@openwave.com>",
                    166:         "Moritz Barsnick <barsnick@gmx.net>",
                    167:         "Thomas Klausner <wiz@NetBSD.org>",
                    168:         NULL
                    169:     };
                    170:   
                    171:   gtk_show_about_dialog(GTK_WINDOW(main_window)
                    172:     , "version", MTR_VERSION
                    173:     , "copyright", "Copyright \xc2\xa9 1997,1998  Matt Kimball"
                    174:     , "website", "http://www.bitwizard.nl/mtr/"
                    175:     , "authors", authors
                    176:     , "comments", "The 'traceroute' and 'ping' programs in a single network diagnostic tool."
                    177:     , "license",
                    178: "This program is free software; you can redistribute it and/or modify\n"
                    179: "it under the terms of the GNU General Public License version 2 as\n"
                    180: "published by the Free Software Foundation.\n"
                    181: "\n"
                    182: "This program is distributed in the hope that it will be useful,\n"
                    183: "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
                    184: "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
                    185: "GNU General Public License for more details."
                    186:   , NULL);
                    187:   return TRUE;
                    188: }
                    189: 
                    190: /*
                    191:  * There is a small problem with the following code:
                    192:  * The timeout is canceled and removed in order to ensure that
                    193:  * it takes effect (consider what happens if you set the timeout to 999,
                    194:  * then try to undo the change); is a better approach possible?
                    195:  *
                    196:  * What's the problem with this? (-> "I don't think so)
                    197:  */
                    198: 
                    199: gint WaitTime_changed(UNUSED GtkAdjustment *Adj, UNUSED GtkWidget *Button) 
                    200: {
                    201:   WaitTime = gtk_spin_button_get_value(GTK_SPIN_BUTTON(Button));
                    202:   g_source_remove (tag);
                    203:   gtk_add_ping_timeout ();
                    204:   gtk_redraw();
                    205: 
                    206:   return FALSE;
                    207: }
                    208: 
                    209: 
                    210: gint Host_activate(GtkWidget *Entry, UNUSED gpointer data) 
                    211: {
                    212:   struct hostent * addr;
                    213: 
                    214:   addr = dns_forward(gtk_entry_get_text(GTK_ENTRY(Entry)));
                    215:   if(addr) {
                    216:     net_reopen(addr);
                    217:     /* If we are "Paused" at this point it is usually because someone
                    218:        entered a non-existing host. Therefore do the go-ahead... */
                    219:     gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( Pause_Button ) , 0);
                    220:   } else {
                    221:     int pos = strlen(gtk_entry_get_text( GTK_ENTRY(Entry)));
                    222:     gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( Pause_Button ) , 1);
                    223:     gtk_editable_insert_text( GTK_EDITABLE(Entry), ": not found", -1, &pos);
                    224:   }
                    225: 
                    226:   return FALSE;
                    227: }
                    228: 
                    229: 
                    230: GdkPixmap *gtk_load_pixmap(char **pixmap) 
                    231: {
                    232:   return gdk_pixmap_colormap_create_from_xpm_d(NULL, 
                    233:                                               gdk_colormap_get_system(), 
                    234:                                               NULL, NULL, pixmap);
                    235: }
                    236: 
                    237: 
                    238: void Toolbar_fill(GtkWidget *Toolbar) 
                    239: {
                    240:   GtkWidget *Button;
                    241:   GtkWidget *Label;
                    242:   GtkAdjustment *Adjustment;
                    243: 
                    244:   Button = gtk_button_new_from_stock(GTK_STOCK_QUIT);
                    245:   gtk_box_pack_end(GTK_BOX(Toolbar), Button, FALSE, FALSE, 0);
                    246:   g_signal_connect(GTK_OBJECT(Button), "clicked",
                    247:                     GTK_SIGNAL_FUNC(Window_destroy), NULL);
                    248: 
                    249:   Button = gtk_button_new_from_stock(GTK_STOCK_ABOUT);
                    250:   gtk_box_pack_end(GTK_BOX(Toolbar), Button, FALSE, FALSE, 0);
                    251:   g_signal_connect(GTK_OBJECT(Button), "clicked",
                    252:                     GTK_SIGNAL_FUNC(About_clicked), NULL);
                    253: 
                    254:   Button = gtk_button_new_with_mnemonic("_Restart");
                    255:   gtk_box_pack_end(GTK_BOX(Toolbar), Button, FALSE, FALSE, 0);
                    256:   g_signal_connect(GTK_OBJECT(Button), "clicked",
                    257:                     GTK_SIGNAL_FUNC(Restart_clicked), NULL);
                    258: 
                    259:   Pause_Button = gtk_toggle_button_new_with_mnemonic("_Pause");
                    260:   gtk_box_pack_end(GTK_BOX(Toolbar), Pause_Button, FALSE, FALSE, 0);
                    261:   g_signal_connect(GTK_OBJECT(Pause_Button), "clicked",
                    262:                     GTK_SIGNAL_FUNC(Pause_clicked), NULL);
                    263: 
                    264:   /* allow root only to set zero delay */
                    265:   Adjustment = (GtkAdjustment *)gtk_adjustment_new(WaitTime,
                    266:                                                   getuid()==0 ? 0.01:1.00,
                    267:                                                  999.99,
                    268:                                                   1.0, 10.0,
                    269:                                                   0.0);
                    270:   Button = gtk_spin_button_new(Adjustment, 0.5, 2);
                    271:   gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(Button), TRUE);
                    272:   /* gtk_spin_button_set_snap_to_ticks(GTK_SPIN_BUTTON(Button), FALSE); */
                    273:   /* gtk_spin_button_set_set_update_policy(GTK_SPIN_BUTTON(Button),
                    274:      GTK_UPDATE_IF_VALID); */
                    275:   gtk_box_pack_end(GTK_BOX(Toolbar), Button, FALSE, FALSE, 0);
                    276:   g_signal_connect(GTK_OBJECT(Adjustment), "value_changed",
                    277:                     GTK_SIGNAL_FUNC(WaitTime_changed), Button);
                    278:  
                    279:   Label = gtk_label_new_with_mnemonic("_Hostname:");
                    280:   gtk_box_pack_start(GTK_BOX(Toolbar), Label, FALSE, FALSE, 0);
                    281: 
                    282:   Entry = gtk_entry_new();
                    283:   gtk_entry_set_text(GTK_ENTRY(Entry), Hostname);
                    284:   g_signal_connect(GTK_OBJECT(Entry), "activate",
                    285:                     GTK_SIGNAL_FUNC(Host_activate), NULL);
                    286:   gtk_box_pack_start(GTK_BOX(Toolbar), Entry, TRUE, TRUE, 0);
                    287:   
                    288:   gtk_label_set_mnemonic_widget(GTK_LABEL(Label), Entry);
                    289: }
                    290: 
                    291: static GtkWidget *ReportTreeView;
                    292: static GtkListStore *ReportStore;
                    293: 
                    294: enum {
                    295:   COL_HOSTNAME,
                    296:   COL_LOSS,
                    297:   COL_RCV,
                    298:   COL_SNT,
                    299:   COL_LAST,
                    300:   COL_BEST,
                    301:   COL_AVG,
                    302:   COL_WORST,
                    303:   COL_STDEV,
                    304:   COL_COLOR,
                    305:   N_COLS
                    306: };
                    307: 
                    308: // Trick to cast a pointer to integer.....
                    309: // We are mis-using a pointer as a single integer. On 64-bit
                    310: // architectures, the pointer is 64 bits and the integer only 32. 
                    311: // The compiler warns us of loss of precision. However we know we
                    312: // casted a normal 32-bit integer into this pointer a few microseconds
                    313: // earlier, so it is ok. Nothing to worry about....
                    314: #define POINTER_TO_INT(p) ((int)(long)(p))
                    315: 
                    316: void  float_formatter(GtkTreeViewColumn *tree_column,
                    317:   GtkCellRenderer   *cell, 
                    318:   GtkTreeModel      *tree_model,
                    319:   GtkTreeIter       *iter, 
                    320:   gpointer           data)
                    321: {
                    322:   gfloat f;
                    323:   gchar text[64];
                    324:   gtk_tree_model_get(tree_model, iter, POINTER_TO_INT(data), &f, -1);
                    325:   sprintf(text, "%.2f", f);
                    326:   g_object_set(cell, "text", text, NULL);
                    327: }
                    328: 
                    329: void  percent_formatter(GtkTreeViewColumn *tree_column,
                    330:   GtkCellRenderer   *cell, 
                    331:   GtkTreeModel      *tree_model,
                    332:   GtkTreeIter       *iter, 
                    333:   gpointer           data)
                    334: {
                    335:   gfloat f;
                    336:   gchar text[64];
                    337:   gtk_tree_model_get(tree_model, iter, POINTER_TO_INT(data), &f, -1);
                    338:   sprintf(text, "%.1f%%", f);
                    339:   g_object_set(cell, "text", text, NULL);
                    340: }
                    341: 
                    342: void TreeViewCreate(void)
                    343: {
                    344:   GtkCellRenderer *renderer;
                    345:   GtkTreeViewColumn *column;
                    346: 
                    347:   ReportStore = gtk_list_store_new(N_COLS,
                    348:     G_TYPE_STRING,
                    349:     G_TYPE_FLOAT,
                    350:     G_TYPE_INT,
                    351:     G_TYPE_INT,
                    352:     G_TYPE_INT,
                    353:     G_TYPE_INT,
                    354:     G_TYPE_INT,
                    355:     G_TYPE_INT,
                    356:     G_TYPE_FLOAT,
                    357:     G_TYPE_STRING
                    358:     );
                    359:     
                    360:   ReportTreeView = gtk_tree_view_new_with_model(GTK_TREE_MODEL(ReportStore));
                    361:   
                    362:   g_signal_connect(GTK_OBJECT(ReportTreeView), "button_press_event", 
                    363:                    G_CALLBACK(ReportTreeView_clicked),NULL);
                    364:   
                    365:   renderer = gtk_cell_renderer_text_new ();
                    366:   column = gtk_tree_view_column_new_with_attributes ("Hostname",
                    367:     renderer,
                    368:     "text", COL_HOSTNAME,
                    369:     "foreground", COL_COLOR,
                    370:     NULL);
                    371:   gtk_tree_view_column_set_expand(column, TRUE);
                    372:   gtk_tree_view_column_set_resizable(column, TRUE);
                    373:   gtk_tree_view_append_column (GTK_TREE_VIEW(ReportTreeView), column);
                    374: 
                    375:   renderer = gtk_cell_renderer_text_new ();
                    376:   g_object_set (G_OBJECT(renderer), "xalign", 1.0, NULL);
                    377:   column = gtk_tree_view_column_new_with_attributes ("Loss",
                    378:     renderer,
                    379:     "text", COL_LOSS,
                    380:     "foreground", COL_COLOR,
                    381:     NULL);
                    382:   gtk_tree_view_column_set_resizable(column, TRUE);
                    383:   gtk_tree_view_column_set_cell_data_func(column, renderer, percent_formatter, (void*)COL_LOSS, NULL);
                    384:   gtk_tree_view_append_column (GTK_TREE_VIEW(ReportTreeView), column);
                    385: 
                    386:   renderer = gtk_cell_renderer_text_new ();
                    387:   g_object_set (G_OBJECT(renderer), "xalign", 1.0, NULL);
                    388:   column = gtk_tree_view_column_new_with_attributes ("Snt",
                    389:     renderer,
                    390:     "text", 3,
                    391:     "foreground", COL_COLOR,
                    392:     NULL);
                    393:   gtk_tree_view_column_set_resizable(column, TRUE);
                    394:   gtk_tree_view_append_column (GTK_TREE_VIEW(ReportTreeView), column);
                    395: 
                    396:   renderer = gtk_cell_renderer_text_new ();
                    397:   g_object_set (G_OBJECT(renderer), "xalign", 1.0, NULL);
                    398:   column = gtk_tree_view_column_new_with_attributes ("Last",
                    399:     renderer,
                    400:     "text", 4,
                    401:     "foreground", COL_COLOR,
                    402:     NULL);
                    403:   gtk_tree_view_column_set_resizable(column, TRUE);
                    404:   gtk_tree_view_append_column (GTK_TREE_VIEW(ReportTreeView), column);
                    405: 
                    406:   renderer = gtk_cell_renderer_text_new ();
                    407:   g_object_set (G_OBJECT(renderer), "xalign", 1.0, NULL);
                    408:   column = gtk_tree_view_column_new_with_attributes ("Avg",
                    409:     renderer,
                    410:     "text", 6,
                    411:     "foreground", COL_COLOR,
                    412:     NULL);
                    413:   gtk_tree_view_column_set_resizable(column, TRUE);
                    414:   gtk_tree_view_append_column (GTK_TREE_VIEW(ReportTreeView), column);
                    415:   
                    416:   renderer = gtk_cell_renderer_text_new ();
                    417:   g_object_set (G_OBJECT(renderer), "xalign", 1.0, NULL);
                    418:   column = gtk_tree_view_column_new_with_attributes ("Best",
                    419:     renderer,
                    420:     "text", 5,
                    421:     "foreground", COL_COLOR,
                    422:     NULL);
                    423:   gtk_tree_view_column_set_resizable(column, TRUE);
                    424:   gtk_tree_view_append_column (GTK_TREE_VIEW(ReportTreeView), column);
                    425: 
                    426:     renderer = gtk_cell_renderer_text_new ();
                    427:   g_object_set (G_OBJECT(renderer), "xalign", 1.0, NULL);
                    428:   column = gtk_tree_view_column_new_with_attributes ("Worst",
                    429:     renderer,
                    430:     "text", 7,
                    431:     "foreground", COL_COLOR,
                    432:     NULL);
                    433:   gtk_tree_view_column_set_resizable(column, TRUE);
                    434:   gtk_tree_view_append_column (GTK_TREE_VIEW(ReportTreeView), column);
                    435: 
                    436:   renderer = gtk_cell_renderer_text_new ();
                    437:   g_object_set (G_OBJECT(renderer), "xalign", 1.0, NULL);
                    438:   column = gtk_tree_view_column_new_with_attributes ("StDev",
                    439:     renderer,
                    440:     "text", 8,
                    441:     "foreground", COL_COLOR,
                    442:     NULL);
                    443:   gtk_tree_view_column_set_resizable(column, TRUE);
                    444:   gtk_tree_view_column_set_cell_data_func(column, renderer, float_formatter, (void*)COL_STDEV, NULL);
                    445:   gtk_tree_view_append_column (GTK_TREE_VIEW(ReportTreeView), column);
                    446: 
                    447: }
                    448: 
                    449: void update_tree_row(int row, GtkTreeIter *iter)
                    450: {
                    451:   ip_t *addr;
                    452:   char str[256]="???", *name=str;
                    453: 
                    454:   addr = net_addr(row);
                    455:   if (addrcmp( (void *) addr, (void *) &unspec_addr, af)) {
                    456:     if ((name = dns_lookup(addr))) {
                    457:       if (show_ips) {
                    458:         snprintf(str, sizeof(str), "%s (%s)", name, strlongip(addr));
                    459:         name = str;
                    460:       }
                    461:     } else name = strlongip(addr);
                    462:   }
                    463: 
                    464:   gtk_list_store_set(ReportStore, iter,
                    465:     COL_HOSTNAME, name,
                    466:     COL_LOSS, (float)(net_loss(row)/1000.0),
                    467: 
                    468:     COL_RCV, net_returned(row),
                    469:     COL_SNT, net_xmit(row),
                    470: 
                    471:     COL_LAST, net_last(row)/1000,
                    472:     COL_BEST, net_best(row)/1000,
                    473:     COL_AVG, net_avg(row)/1000,
                    474:     COL_WORST, net_worst(row)/1000,
                    475:     COL_STDEV, (float)(net_stdev(row)/1000.0),
                    476:     
                    477:     COL_COLOR, net_up(row) ? "black" : "red",
                    478: 
                    479:     -1);
                    480: }
                    481: 
                    482: void gtk_redraw(void)
                    483: {
                    484:   int max = net_max();
                    485:   
                    486:   GtkTreeIter iter;
                    487:   int row = net_min();
                    488:   gboolean valid;
                    489: 
                    490:   valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(ReportStore), &iter);
                    491: 
                    492:   while(valid) {
                    493:     if(row < max) {
                    494:       update_tree_row(row++, &iter);
                    495:       valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(ReportStore), &iter);
                    496:     } else {
                    497:       valid = gtk_list_store_remove(ReportStore, &iter);
                    498:     }
                    499:   }
                    500:   while(row < max) {
                    501:     gtk_list_store_append(ReportStore, &iter);
                    502:     update_tree_row(row++, &iter);
                    503:   }
                    504: }
                    505: 
                    506: 
                    507: void Window_fill(GtkWidget *Window) 
                    508: {
                    509:   GtkWidget *VBox;
                    510:   GtkWidget *Toolbar;
                    511:   GtkWidget *scroll;
                    512: 
                    513:   gtk_window_set_title(GTK_WINDOW(Window), "My traceroute");
                    514:   gtk_window_set_default_size(GTK_WINDOW(Window), 650, 400); 
                    515:   gtk_container_set_border_width(GTK_CONTAINER(Window), 10);
                    516:   VBox = gtk_vbox_new(FALSE, 10);
                    517: 
                    518:   Toolbar = gtk_hbox_new(FALSE, 10);
                    519:   Toolbar_fill(Toolbar);
                    520:   gtk_box_pack_start(GTK_BOX(VBox), Toolbar, FALSE, FALSE, 0);
                    521:   
                    522:   TreeViewCreate();
                    523:   scroll = gtk_scrolled_window_new(NULL, NULL);
                    524:   gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
                    525:   gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll), GTK_SHADOW_IN);
                    526:   gtk_container_add(GTK_CONTAINER(scroll), ReportTreeView);
                    527:   gtk_box_pack_start(GTK_BOX(VBox), scroll, TRUE, TRUE, 0);
                    528: 
                    529:   gtk_container_add(GTK_CONTAINER(Window), VBox);
                    530: }
                    531: 
                    532: 
                    533: void gtk_open(void)
                    534: {
                    535:   GdkPixbuf *icon;
                    536: 
                    537:   int argc;
                    538:   char *args[2];
                    539:   char **argv;
                    540:   argc = 1;
                    541:   argv = args;
                    542:   argv[0] = "";
                    543:   argv[1] = NULL;
                    544:   gtk_do_init(&argc, &argv);
                    545: 
                    546:   icon = gdk_pixbuf_new_from_xpm_data((const char**)mtr_icon);
                    547:   gtk_window_set_default_icon(icon);
                    548: 
                    549:   main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
                    550:   
                    551:   g_set_application_name("My traceroute");
                    552: 
                    553:   Window_fill(main_window);
                    554: 
                    555:   g_signal_connect(GTK_OBJECT(main_window), "delete_event",
                    556:                      GTK_SIGNAL_FUNC(Window_destroy), NULL);
                    557:   g_signal_connect(GTK_OBJECT(main_window), "destroy",
                    558:                     GTK_SIGNAL_FUNC(Window_destroy), NULL);
                    559: 
                    560:   gtk_widget_show_all(main_window);
                    561: }
                    562: 
                    563: 
                    564: void gtk_close(void)
                    565: {
                    566: }
                    567: 
                    568: 
                    569: int gtk_keyaction(void)
                    570: {
                    571:   return 0;
                    572: }
                    573: 
                    574: 
                    575: gint gtk_ping(UNUSED gpointer data) 
                    576: {
                    577:   gtk_redraw();
                    578:   net_send_batch();
                    579:   net_harvest_fds();
                    580:   g_source_remove (tag);
                    581:   gtk_add_ping_timeout ();
                    582:   return TRUE;
                    583: }
                    584: 
                    585: 
                    586: gboolean gtk_net_data(UNUSED GIOChannel *channel, UNUSED GIOCondition cond, UNUSED gpointer data) 
                    587: {
                    588:   net_process_return();
                    589:   return TRUE;
                    590: }
                    591: 
                    592: 
                    593: gboolean gtk_dns_data(UNUSED GIOChannel *channel, UNUSED GIOCondition cond, UNUSED gpointer data)
                    594: {
                    595:   dns_ack();
                    596:   gtk_redraw();
                    597:   return TRUE;
                    598: }
                    599: #ifdef ENABLE_IPV6
                    600: gboolean gtk_dns_data6(UNUSED GIOChannel *channel, UNUSED GIOCondition cond, UNUSED gpointer data)
                    601: {
                    602:   dns_ack6();
                    603:   gtk_redraw();
                    604:   return TRUE;
                    605: }
                    606: #endif
                    607: 
                    608: 
                    609: void gtk_loop(void) 
                    610: {
                    611:   GIOChannel *net_iochannel, *dns_iochannel;
                    612: 
                    613:   gtk_add_ping_timeout ();
                    614:   
                    615:   net_iochannel = g_io_channel_unix_new(net_waitfd());
                    616:   g_io_add_watch(net_iochannel, G_IO_IN, gtk_net_data, NULL);
                    617: #ifdef ENABLE_IPV6
1.1.1.2 ! misho     618:   if (dns_waitfd6() > 0) {
        !           619:     dns_iochannel = g_io_channel_unix_new(dns_waitfd6());
        !           620:     g_io_add_watch(dns_iochannel, G_IO_IN, gtk_dns_data6, NULL);
        !           621:   }
1.1       misho     622: #endif
                    623:   dns_iochannel = g_io_channel_unix_new(dns_waitfd());
                    624:   g_io_add_watch(dns_iochannel, G_IO_IN, gtk_dns_data, NULL);
                    625: 
                    626:   gtk_main();
                    627: }
                    628: 
                    629: gboolean NewDestination_activate(GtkWidget *widget, gpointer data)
                    630: {
                    631:   gchar *hostname;
                    632:   GtkTreePath *path = (GtkTreePath*)data;
                    633:        
                    634:   hostname = getSelectedHost(path);
                    635:   if (hostname) {
                    636:     gtk_entry_set_text (GTK_ENTRY(Entry), hostname);
                    637:     Host_activate(Entry, NULL);
                    638:     g_free(hostname);
                    639:   }
                    640:   return TRUE;
                    641: }
                    642: 
                    643: 
                    644: gboolean Copy_activate(GtkWidget *widget, gpointer data)
                    645: {
                    646:   gchar *hostname;
                    647:   GtkTreePath *path = (GtkTreePath*)data;
                    648:        
                    649:   hostname = getSelectedHost(path);
                    650:   if (hostname != NULL) {
                    651:     GtkClipboard *clipboard;
                    652: 
                    653:     clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
                    654:     gtk_clipboard_set_text(clipboard, hostname, -1);
                    655: 
                    656:     clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY);
                    657:     gtk_clipboard_set_text(clipboard, hostname, -1);
                    658: 
                    659:     g_free(hostname);
                    660:   }
                    661: 
                    662:   return TRUE;
                    663: }
                    664: 
                    665: gchar *getSelectedHost(GtkTreePath *path)
                    666: {
                    667:   GtkTreeIter iter;
                    668:   gchar *name = NULL;
                    669: 
                    670:   if (gtk_tree_model_get_iter(GTK_TREE_MODEL(ReportStore), &iter, path)) {
                    671:     gtk_tree_model_get (GTK_TREE_MODEL(ReportStore), &iter, COL_HOSTNAME, &name, -1);
                    672:   }
                    673:   gtk_tree_path_free(path);
                    674:   return name;
                    675: }
                    676: 
                    677: 
                    678: gboolean ReportTreeView_clicked(GtkWidget *Tree, GdkEventButton *event)
                    679: {
                    680:   GtkWidget* popup_menu; 
                    681:   GtkWidget* copy_item; 
                    682:   GtkWidget* newdestination_item;
                    683:   GtkTreePath *path;
                    684: 
                    685:   if (event->type != GDK_BUTTON_PRESS  || event->button != 3)
                    686:     return FALSE;
                    687: 
                    688:   if(!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(ReportTreeView),
                    689:       event->x, event->y, &path, NULL, NULL, NULL))
                    690:     return FALSE;
                    691:   
                    692:   gtk_tree_view_set_cursor(GTK_TREE_VIEW(ReportTreeView), path, NULL, FALSE);
                    693: 
                    694:   // Single right click: prepare and show the popup menu
                    695:   popup_menu = gtk_menu_new ();
                    696: 
                    697:   copy_item = gtk_menu_item_new_with_label ("Copy to clipboard");
                    698:   newdestination_item = gtk_menu_item_new_with_label ("Set as new destination"); 
                    699: 
                    700:   gtk_menu_append (GTK_MENU (popup_menu), copy_item); 
                    701:   gtk_menu_append (GTK_MENU (popup_menu), newdestination_item); 
                    702: 
                    703:   g_signal_connect(GTK_OBJECT(copy_item),"activate",
                    704:                    GTK_SIGNAL_FUNC(Copy_activate), path);
                    705: 
                    706:   g_signal_connect(GTK_OBJECT(newdestination_item),"activate",
                    707:                    GTK_SIGNAL_FUNC(NewDestination_activate), path);
                    708:               
                    709:   gtk_widget_show (copy_item); 
                    710:   gtk_widget_show (newdestination_item); 
                    711: 
                    712:   gtk_menu_popup (GTK_MENU(popup_menu), NULL, NULL, NULL, NULL,
                    713:                    0, event->time);
                    714:   return TRUE;
                    715: }
                    716: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>