"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 */