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

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: 
        !            20: #include <config.h>
        !            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
        !           618:   dns_iochannel = g_io_channel_unix_new(dns_waitfd6());
        !           619:   g_io_add_watch(dns_iochannel, G_IO_IN, gtk_dns_data6, NULL);
        !           620: #endif
        !           621:   dns_iochannel = g_io_channel_unix_new(dns_waitfd());
        !           622:   g_io_add_watch(dns_iochannel, G_IO_IN, gtk_dns_data, NULL);
        !           623: 
        !           624:   gtk_main();
        !           625: }
        !           626: 
        !           627: gboolean NewDestination_activate(GtkWidget *widget, gpointer data)
        !           628: {
        !           629:   gchar *hostname;
        !           630:   GtkTreePath *path = (GtkTreePath*)data;
        !           631:        
        !           632:   hostname = getSelectedHost(path);
        !           633:   if (hostname) {
        !           634:     gtk_entry_set_text (GTK_ENTRY(Entry), hostname);
        !           635:     Host_activate(Entry, NULL);
        !           636:     g_free(hostname);
        !           637:   }
        !           638:   return TRUE;
        !           639: }
        !           640: 
        !           641: 
        !           642: gboolean Copy_activate(GtkWidget *widget, gpointer data)
        !           643: {
        !           644:   gchar *hostname;
        !           645:   GtkTreePath *path = (GtkTreePath*)data;
        !           646:        
        !           647:   hostname = getSelectedHost(path);
        !           648:   if (hostname != NULL) {
        !           649:     GtkClipboard *clipboard;
        !           650: 
        !           651:     clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
        !           652:     gtk_clipboard_set_text(clipboard, hostname, -1);
        !           653: 
        !           654:     clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY);
        !           655:     gtk_clipboard_set_text(clipboard, hostname, -1);
        !           656: 
        !           657:     g_free(hostname);
        !           658:   }
        !           659: 
        !           660:   return TRUE;
        !           661: }
        !           662: 
        !           663: gchar *getSelectedHost(GtkTreePath *path)
        !           664: {
        !           665:   GtkTreeIter iter;
        !           666:   gchar *name = NULL;
        !           667: 
        !           668:   if (gtk_tree_model_get_iter(GTK_TREE_MODEL(ReportStore), &iter, path)) {
        !           669:     gtk_tree_model_get (GTK_TREE_MODEL(ReportStore), &iter, COL_HOSTNAME, &name, -1);
        !           670:   }
        !           671:   gtk_tree_path_free(path);
        !           672:   return name;
        !           673: }
        !           674: 
        !           675: 
        !           676: gboolean ReportTreeView_clicked(GtkWidget *Tree, GdkEventButton *event)
        !           677: {
        !           678:   GtkWidget* popup_menu; 
        !           679:   GtkWidget* copy_item; 
        !           680:   GtkWidget* newdestination_item;
        !           681:   GtkTreePath *path;
        !           682: 
        !           683:   if (event->type != GDK_BUTTON_PRESS  || event->button != 3)
        !           684:     return FALSE;
        !           685: 
        !           686:   if(!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(ReportTreeView),
        !           687:       event->x, event->y, &path, NULL, NULL, NULL))
        !           688:     return FALSE;
        !           689:   
        !           690:   gtk_tree_view_set_cursor(GTK_TREE_VIEW(ReportTreeView), path, NULL, FALSE);
        !           691: 
        !           692:   // Single right click: prepare and show the popup menu
        !           693:   popup_menu = gtk_menu_new ();
        !           694: 
        !           695:   copy_item = gtk_menu_item_new_with_label ("Copy to clipboard");
        !           696:   newdestination_item = gtk_menu_item_new_with_label ("Set as new destination"); 
        !           697: 
        !           698:   gtk_menu_append (GTK_MENU (popup_menu), copy_item); 
        !           699:   gtk_menu_append (GTK_MENU (popup_menu), newdestination_item); 
        !           700: 
        !           701:   g_signal_connect(GTK_OBJECT(copy_item),"activate",
        !           702:                    GTK_SIGNAL_FUNC(Copy_activate), path);
        !           703: 
        !           704:   g_signal_connect(GTK_OBJECT(newdestination_item),"activate",
        !           705:                    GTK_SIGNAL_FUNC(NewDestination_activate), path);
        !           706:               
        !           707:   gtk_widget_show (copy_item); 
        !           708:   gtk_widget_show (newdestination_item); 
        !           709: 
        !           710:   gtk_menu_popup (GTK_MENU(popup_menu), NULL, NULL, NULL, NULL,
        !           711:                    0, event->time);
        !           712:   return TRUE;
        !           713: }
        !           714: 

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