"Fossies" - the Fresh Open Source Software Archive

Member "netbiff-0.9.18/gui_gtk.c" (7 Aug 2004, 11476 Bytes) of package /linux/privat/old/netbiff-0.9.18.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 #include "gtk.h"
    2 #include "gui.h"
    3 
    4 #ifndef GUI_GTK
    5 
    6 GUI *gui_gtk_description = NULL;
    7 
    8 #else
    9 
   10 #include <gtk/gtk.h>
   11 #include <stdlib.h>
   12 #include <string.h>
   13 #include <time.h>
   14 #include <stdio.h>
   15 
   16 #include "conf.h"
   17 #include "connection.h"
   18 #include "proto.h"
   19 #include "xlib.h"
   20 
   21 #include "flagup.xpm"
   22 #include "flagdown.xpm"
   23 #include "yes.xpm"
   24 #include "no.xpm"
   25 
   26 static GdkPixmap *flagup;
   27 static GdkBitmap *upmask;
   28 static GdkPixmap *flagdown;
   29 static GdkBitmap *downmask;
   30 
   31 static GdkPixmap *yes;
   32 static GdkBitmap *yesmask;
   33 static GdkPixmap *no;
   34 static GdkBitmap *nomask;
   35 
   36 static GtkWidget *main_window;
   37 static GtkWidget *flag;
   38 
   39 static GtkWidget *status_window;
   40 static int status_shown = 0;
   41 static GtkWidget *status_table;
   42 static GtkWidget *status_statusbar;
   43 static guint status_size;
   44 static guint status_context;
   45 
   46 static GtkWidget *connection_images[MAX_CONNECTIONS];
   47 
   48 static void gtk_flagup(const Connection *c) {
   49   if(c) 
   50     gtk_pixmap_set(GTK_PIXMAP(connection_images[c-connections]), yes, yesmask);
   51   gtk_pixmap_set(GTK_PIXMAP(flag), flagup, upmask);
   52 }
   53 
   54 static void gtk_flagdown(const Connection *c) {
   55   int i, j;
   56   int biffed;
   57 
   58   if(c) 
   59     gtk_pixmap_set(GTK_PIXMAP(connection_images[c-connections]), no, nomask);
   60 
   61   biffed = 0;
   62   for(i = 0; i < nconnections; i++) {
   63     for(j = 0; j < connections[i].nfolders; j++) {
   64       if(connections[i].folders[j].biffed) {
   65         biffed++;
   66       }
   67     }
   68   }
   69 
   70   if(!biffed)
   71     gtk_pixmap_set(GTK_PIXMAP(flag), flagdown, downmask);
   72 }
   73 
   74 static gint hide_status() {
   75   status_shown = 0;
   76   gtk_widget_hide(status_window);
   77   return TRUE;
   78 }
   79 
   80 static gint show_status() {
   81   int winx, winy;
   82 
   83   status_shown = 1;
   84   
   85   gdk_window_get_position(main_window->window, &winx, &winy);
   86   gtk_widget_set_uposition(status_window,
   87       winx + main_window->allocation.width,
   88       winy + main_window->allocation.height);
   89   
   90   gtk_widget_show_all(status_window);
   91 
   92   return TRUE;
   93 }
   94 
   95 static gint image_clicked(GtkWidget *widget, GdkEventButton *event,
   96     gpointer data) {
   97   switch(event->button) {
   98     case 1:
   99       gtk_pixmap_set(GTK_PIXMAP(flag), flagdown, downmask);
  100       break;
  101     case 3:
  102       if(status_shown)
  103         hide_status();
  104       else
  105         show_status();
  106       break;
  107   }
  108   return TRUE;
  109 }
  110 
  111 static gint statusbar_clicked(GtkWidget *widget, GdkEventButton *event, 
  112     gpointer data) {
  113   switch(event->button) {
  114     case 1:
  115       gtk_statusbar_pop(GTK_STATUSBAR(status_statusbar), status_context);
  116       break;
  117     case 2:
  118       while(status_size) {
  119         gtk_statusbar_pop(GTK_STATUSBAR(status_statusbar), status_context);
  120         status_size--;
  121       }
  122       break;
  123   }
  124   return TRUE;
  125 }
  126 
  127 void main_window_create() {
  128   main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  129   gtk_signal_connect(GTK_OBJECT(main_window), "delete_event",
  130       GTK_SIGNAL_FUNC(gtk_main_quit), NULL);
  131   gtk_signal_connect(GTK_OBJECT(main_window), "destroy",
  132       GTK_SIGNAL_FUNC(gtk_main_quit), NULL);
  133   gtk_container_border_width(GTK_CONTAINER(main_window), 0);
  134   gtk_window_set_title(GTK_WINDOW(main_window), "NetBiff");
  135 
  136   gtk_widget_set_events(main_window, 
  137       gtk_widget_get_events(main_window) | GDK_BUTTON_PRESS_MASK);
  138   gtk_signal_connect(GTK_OBJECT(main_window), "button_press_event",
  139       GTK_SIGNAL_FUNC(image_clicked), NULL); 
  140 
  141   gtk_widget_realize(main_window);
  142 }
  143 
  144 void pixmap_create() {
  145   GtkStyle *style;
  146   style = gtk_widget_get_style(main_window);
  147 
  148   flagdown = gdk_pixmap_create_from_xpm_d(main_window->window,
  149                                           &downmask,
  150                                           &style->black,
  151                                           (gchar **)flagdown_data);
  152   flagup = gdk_pixmap_create_from_xpm_d(main_window->window,
  153                                          &upmask,
  154                                          &style->white,
  155                                          (gchar **)flagup_data);
  156   
  157   flag = gtk_pixmap_new(flagdown, downmask);
  158   gtk_container_add(GTK_CONTAINER(main_window), flag);
  159 
  160   yes = gdk_pixmap_create_from_xpm_d(main_window->window,
  161       &yesmask, style->bg, (gchar **)yes_xpm);
  162   no = gdk_pixmap_create_from_xpm_d(main_window->window,
  163       &nomask, style->bg, (gchar **)no_xpm);
  164 }
  165 
  166 void status_window_create() {
  167   GtkWidget *box;
  168 
  169   status_window = gtk_window_new(GTK_WINDOW_POPUP);
  170   gtk_container_border_width(GTK_CONTAINER(status_window), 2);
  171   gtk_window_set_transient_for(GTK_WINDOW(status_window), 
  172       GTK_WINDOW(main_window));
  173   gtk_window_set_policy(GTK_WINDOW(status_window), 1, 1, 1);
  174   gtk_signal_connect(GTK_OBJECT(status_window), "delete_event",
  175       GTK_SIGNAL_FUNC(hide_status), NULL);
  176 
  177   box = gtk_vbox_new(0, FALSE);
  178   gtk_container_add(GTK_CONTAINER(status_window), box);
  179 
  180   status_table = gtk_table_new(1, 2, FALSE);
  181   gtk_table_set_row_spacings(GTK_TABLE(status_table), 0);
  182   gtk_table_set_col_spacings(GTK_TABLE(status_table), 5);
  183   gtk_box_pack_start(GTK_BOX(box), status_table, FALSE, FALSE, 0);
  184 
  185   gtk_table_attach_defaults(GTK_TABLE(status_table),
  186       gtk_label_new("Connection"), 0, 1, 0, 1);
  187   gtk_table_attach_defaults(GTK_TABLE(status_table), 
  188       gtk_label_new("Status"), 1, 2, 0, 1);
  189 
  190   status_statusbar = gtk_statusbar_new();
  191   gtk_box_pack_start(GTK_BOX(box), status_statusbar, FALSE, FALSE, 0);
  192   status_context = gtk_statusbar_get_context_id(
  193       GTK_STATUSBAR(status_statusbar), "Netbiff");
  194   
  195   gtk_widget_set_events(status_window,
  196       gtk_widget_get_events(status_window) | GDK_BUTTON_PRESS_MASK);
  197   gtk_signal_connect(GTK_OBJECT(status_window), "button_press_event",
  198       GTK_SIGNAL_FUNC(statusbar_clicked), NULL);
  199 }
  200 
  201 static void gtk_gui_init(int *argc, char ***argv) {
  202   char **a;
  203 
  204   gtk_init(argc, argv);
  205   /* The original argv may not be available, so gtk's guess for the
  206    * program class will be wrong. */
  207   gdk_set_program_class("Netbiff");
  208 
  209   main_window_create();
  210   pixmap_create();
  211   status_window_create();
  212 
  213   a = *argv;
  214   while(*++a) {
  215     if(!strcmp(*a, "-geometry")) {
  216       a++;
  217       if(!*a) {
  218         xerror("-geometry requires value on command line");
  219         continue;
  220       }
  221       else {
  222         if(!gtk_window_parse_geometry(GTK_WINDOW(main_window), *a)) {
  223           xerror("invalid format for -geometry");
  224           continue;
  225         }
  226       }
  227     }
  228     else if(!strcmp(*a, "--"))
  229       continue;
  230     else {
  231       xerror("Unrecognized option: %s", *a);
  232     }
  233   }
  234 }
  235 
  236 static int gtk_display_message(const char *fmt, va_list ap) {
  237   char buf[4096];
  238   unsigned long len;
  239   time_t t;
  240   const struct tm *tm;
  241   
  242   t = time(NULL);
  243   tm = localtime(&t);
  244   len = strftime(buf, sizeof(buf), "%H:%M:%S ", tm);
  245   vsnprintf(buf + len, sizeof(buf) - len, fmt, ap);
  246 
  247   if(GTK_WIDGET_VISIBLE(main_window)) {
  248     gtk_statusbar_push(GTK_STATUSBAR(status_statusbar), status_context, buf);
  249     status_size++;
  250   }
  251   else {
  252     fputs(buf, stderr);
  253     putc('\n', stderr);
  254   }
  255 
  256   return 0;
  257 }
  258 
  259 static int gtk_poll_shim(void *data) {
  260   proto_do_poll();
  261   return TRUE;
  262 }
  263 
  264 static int gtk_retry_shim(void *data) {
  265   proto_do_retries();
  266   return FALSE;
  267 }
  268 
  269 static void gtk_event_loop() {
  270   gtk_timeout_add(poll_frequency * 1000, gtk_poll_shim, NULL);
  271   gtk_widget_show_all(main_window);
  272   gtk_main();
  273 }
  274 
  275 static void gtk_beep() {
  276   gdk_beep();
  277 }
  278 
  279 struct taglist {
  280   const Connection *c;
  281   int type;
  282   int tag;
  283   struct taglist *next;
  284   struct taglist *prev;
  285 };
  286 static struct taglist *taghead, *tagtail = NULL;
  287 
  288 static void taglist_add(const Connection *c, int type, int tag) {
  289   struct taglist *t;
  290 
  291   t = xmalloc(sizeof(struct taglist));
  292   t->c = c;
  293   t->type = type;
  294   t->tag = tag;
  295   t->prev = tagtail;
  296   t->next = NULL;
  297   if(tagtail)
  298     tagtail->next = t;
  299   else
  300     taghead = t;
  301   tagtail = t;
  302 }
  303 
  304 static int taglist_find_and_delete(const Connection *c, int type) {
  305   struct taglist *t;
  306 
  307   for(t = taghead; t; t = t->next) {
  308     if(t->c == c && t->type == type) {
  309       int tag = t->tag;
  310       if(t->next)
  311         t->next->prev = t->prev;
  312       else
  313         tagtail = t->prev;
  314       if(t->prev) 
  315         t->prev->next = t->next;
  316       else
  317         taghead = t->next;
  318       free(t);
  319       return tag;
  320     }
  321   }
  322   return -1;
  323 }
  324 
  325 static void gtk_io_shim(Connection *c, gint fd, GdkInputCondition cond) {
  326   switch(cond) {
  327     case GDK_INPUT_READ: proto_do_conn_input(c); break;
  328     case GDK_INPUT_WRITE: proto_do_conn_output(c); break;
  329     default: break;
  330   }
  331 }
  332 
  333 static void gtk_add_fd(const Connection *c, int type) {
  334   if(type & GUI_FD_READ) {
  335     int tag;
  336 
  337     tag = gdk_input_add(c->fd_in, GDK_INPUT_READ,
  338         (GdkInputFunction)gtk_io_shim, (gpointer)c);
  339     taglist_add(c, GUI_FD_READ, tag);
  340   }
  341   if(type & GUI_FD_WRITE) {
  342     int tag;
  343 
  344     tag = gdk_input_add(c->fd_out, GDK_INPUT_WRITE,
  345        (GdkInputFunction)gtk_io_shim, (gpointer)c);
  346     taglist_add(c, GUI_FD_WRITE, tag);
  347   }
  348 }
  349 
  350 static void gtk_delete_fd(const Connection *c, int type) {
  351   int tag;
  352 
  353   if(type & GUI_FD_READ) {
  354     tag = taglist_find_and_delete(c, GUI_FD_READ);
  355     if(tag >= 0)
  356       gdk_input_remove(tag);
  357   }
  358   if(type & GUI_FD_WRITE) {
  359     tag = taglist_find_and_delete(c, GUI_FD_WRITE);
  360     if(tag >= 0)
  361       gdk_input_remove(tag);
  362   }
  363 }
  364 
  365 static const char *request_buffer = NULL;
  366 static void request_callback(GtkWidget *w, gpointer data) {
  367   request_buffer = gtk_entry_get_text(GTK_ENTRY(w));
  368 }
  369 
  370 static gint request_delete(GtkWidget *w, GdkEvent *e, gpointer data) {
  371   request_buffer = "";
  372   return TRUE;
  373 }
  374 
  375 
  376 static int pending_request = 0;
  377 static char *gtk_request_data(const char *prompt, int hidden) {
  378   GtkWidget *dialog;
  379   GtkWidget *input_box;
  380   GtkWidget *label;
  381   char *retval;
  382 
  383   if(pending_request)
  384     return NULL;
  385 
  386   pending_request = 1;
  387 
  388   dialog = gtk_dialog_new();
  389   gtk_signal_connect(GTK_OBJECT(dialog), "delete_event", 
  390       GTK_SIGNAL_FUNC(request_delete), NULL);
  391 
  392   label = gtk_label_new("A module has requested the data:");
  393   gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), 
  394       label, 0, FALSE, FALSE);
  395   label = gtk_label_new(prompt);
  396   gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), 
  397       label, 0, FALSE, FALSE);
  398 
  399   input_box = gtk_entry_new();
  400   if(hidden)
  401     gtk_entry_set_visibility(GTK_ENTRY(input_box), FALSE);
  402   gtk_entry_set_editable(GTK_ENTRY(input_box), TRUE);
  403   gtk_signal_connect(GTK_OBJECT(input_box), "activate", 
  404       GTK_SIGNAL_FUNC(request_callback), NULL);
  405   gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
  406       input_box, 0, TRUE, TRUE);
  407 
  408   gtk_widget_show_all(dialog);
  409   gtk_grab_add(dialog);
  410 
  411   while(!request_buffer)
  412     g_main_iteration(TRUE);
  413 
  414   retval = strdup(request_buffer);
  415 
  416   gtk_grab_remove(dialog);
  417   gtk_widget_destroy(dialog);
  418 
  419   request_buffer = NULL;
  420   pending_request = 0;
  421 
  422   return retval;
  423 }
  424 
  425 static void gtk_register_connections() {
  426   int i;
  427 
  428   for(i = 0; i < nconnections; i++) {
  429     connection_images[i] = gtk_pixmap_new(no, nomask);
  430     gtk_table_attach_defaults(GTK_TABLE(status_table), 
  431         gtk_label_new(connections[i].name),
  432         0, 1, 
  433         i+1, i+2);
  434     gtk_table_attach_defaults(GTK_TABLE(status_table), 
  435         connection_images[i],
  436         1, 2, 
  437         i+1, i+2);
  438   }
  439 }
  440 
  441 static void gtk_schedule_retry(time_t when) {
  442   time_t now;
  443 
  444   now = time(0);
  445 
  446   if(when < now)
  447     when = now;
  448 
  449   gtk_timeout_add((when - now) * 1000, gtk_retry_shim, NULL);
  450 }
  451 
  452 static GUI gui_gtk = {
  453   gtk_flagup,
  454   gtk_flagdown,
  455   gtk_gui_init,
  456   gtk_display_message,
  457   gtk_event_loop,
  458   gtk_beep,
  459   gtk_add_fd,
  460   gtk_delete_fd,
  461   gtk_request_data,
  462   gtk_register_connections,
  463   gtk_schedule_retry
  464 };
  465 GUI *gui_gtk_description = &gui_gtk;
  466 
  467 #endif /* GUI_GTK */