0.8.0
[geeqie.git] / src / image.c
1 /*
2  * GQview image viewer
3  * (C)2000 John Ellis
4  *
5  * Author: John Ellis
6  *
7  */
8
9 #include "gqview.h"
10 #include "image.h"
11 #include "icons/img_unknown.xpm"
12 #include <gdk/gdkx.h>
13
14 static gchar *zoom_as_text(gint zoom, gfloat scale);
15 static void set_zoom_label(GtkWidget *label, gint zoom, gfloat scale);
16 static void set_info_label(GtkWidget *label, gint width, gint height, gint size, gint unknown);
17 static void set_window_title(ImageWindow *imd, gchar *text);
18
19 static gint image_area_size_top_window(ImageWindow *imd, gint w, gint h);
20
21 static void image_area_recalc_size(ImageWindow *imd, GtkAllocation *allocation);
22
23 static void image_area_redraw(ImageWindow *imd);
24 static gint image_area_size_cb(GtkWidget *widget, GtkAllocation *allocation, gpointer data);
25 static gint image_area_update_cb(GtkWidget *widget, GdkEventConfigure *event, gpointer data);
26
27 static void set_mouse_cursor (GdkWindow *window, gint icon);
28 static void image_area_mouse_moved(GtkWidget *widget, GdkEventButton *bevent, gpointer data);
29 static void image_area_mouse_pressed(GtkWidget *widget, GdkEventButton *bevent, gpointer data);
30 static void image_area_mouse_released(GtkWidget *widget, GdkEventButton *bevent, gpointer data);
31 static void image_area_mouse_drag(GtkWidget *widget, GdkDragContext *context, gpointer data);
32
33 /*
34  *-----------------------------------------------------------------------------
35  * image status widget update routines (private)
36  *-----------------------------------------------------------------------------
37  */
38
39 static gchar *zoom_as_text(gint zoom, gfloat scale)
40 {
41         gint l = 1;
42         gint r = 1;
43         gchar *approx = " ";
44         if (zoom > 1) l = zoom;
45         if (zoom < -1) r = -zoom;
46         if (zoom == 0 && scale != 0)
47                 {
48                 if (scale < 1) r = 1 / scale + 0.5;
49                 approx = " ~";
50                 }
51         return g_strdup_printf("%d :%s%d", l, approx, r);
52 }
53
54 static void set_zoom_label(GtkWidget *label, gint zoom, gfloat scale)
55 {
56         gchar *buf;
57         buf = zoom_as_text(zoom, scale);
58         gtk_label_set(GTK_LABEL(label), buf);
59         g_free(buf);
60 }
61
62 static void set_info_label(GtkWidget *label, gint width, gint height, gint size, gint unknown)
63 {
64         gchar buf[64];
65         if (unknown)
66                 sprintf(buf, _("( ? x ? ) %d bytes"), size);
67         else
68                 sprintf(buf, _("( %d x %d ) %d bytes"), width, height, size);
69         gtk_label_set(GTK_LABEL(label), buf);
70 }
71
72 static void set_window_title(ImageWindow *imd, gchar *text)
73 {
74         gchar *title = NULL;
75         if (!imd->top_window) return;
76
77         if (imd->title)
78                 {
79                 title = g_strconcat(imd->title, imd->image_name, text, NULL);
80                 }
81         else
82                 {
83                 title = g_strconcat(imd->image_name, text, NULL);
84                 }
85
86         gtk_window_set_title(GTK_WINDOW(imd->top_window), title);
87         g_free(title);
88 }
89
90 /*
91  *-----------------------------------------------------------------------------
92  * fit window to image utility (private)
93  *-----------------------------------------------------------------------------
94  */ 
95
96 static gint image_area_size_top_window(ImageWindow *imd, gint w, gint h)
97 {
98         if (!imd->top_window) return FALSE;
99         if (imd == full_screen_image) return FALSE;
100         if (imd == normal_image && !toolwindow) return FALSE;
101         if (!fit_window) return FALSE;
102
103         if (imd == normal_image)
104                 {
105                 /* account for border frame */
106                 w += 4;
107                 h += 4;
108                 }
109
110         if (limit_window_size)
111                 {
112                 gint sw = gdk_screen_width() * max_window_size / 100;
113                 gint sh = gdk_screen_height() * max_window_size / 100;
114
115                 if (w > sw) w = sw;
116                 if (h > sh) h = sh;
117                 }
118
119         /* to cheat on a prob a little, don't resize if within 1 either way...
120            ...dumb off by 1 errors! ;) */
121
122 /*      if (w >= (imd->top_window)->allocation.width - 1 &&
123             w <= (imd->top_window)->allocation.width + 1 &&
124             h >= (imd->top_window)->allocation.height - 1 &&
125             h <= (imd->top_window)->allocation.height + 1)
126                 return FALSE;
127 */
128         if (debug) printf("auto sized to %d x %d\n", w, h);
129
130         gdk_window_resize(imd->top_window->window, w, h);
131         gtk_widget_set_usize(imd->top_window, w, h);
132
133         return TRUE;
134 }
135
136 /*
137  *-----------------------------------------------------------------------------
138  * image widget zoom/recalc routines
139  *-----------------------------------------------------------------------------
140  */ 
141
142 void image_area_scroll(ImageWindow *imd, gint x, gint y)
143 {
144         if (x != 0)
145                 {
146                 GtkAdjustment *h = gtk_viewport_get_hadjustment(GTK_VIEWPORT(imd->viewport));
147                 gfloat val = h->value + x;
148                 if (val < h->lower) val = h->lower;
149                 if (val > h->upper - h->page_size) val = h->upper - h->page_size;
150                 gtk_adjustment_set_value(GTK_ADJUSTMENT(h), val);
151                 }
152
153         if (y != 0)
154                 {
155                 GtkAdjustment *v = gtk_viewport_get_vadjustment(GTK_VIEWPORT(imd->viewport));
156                 gfloat val = v->value + y;
157                 if (val < v->lower) val = v->lower;
158                 if (val > v->upper - v->page_size) val = v->upper - v->page_size;
159                 gtk_adjustment_set_value(GTK_ADJUSTMENT(v), val);
160                 }
161 }
162
163 gint image_area_get_zoom(ImageWindow *imd)
164 {
165         return imd->zoom;
166 }
167
168 void image_area_adjust_zoom(ImageWindow *imd, gint increment)
169 {
170         gint zoom = imd->zoom;
171         if (increment < 0)
172                 {
173                 while (increment < 0)
174                         {
175                         zoom--;
176                         if (zoom == 0 || zoom == -1) zoom = -2;
177                         increment++;
178                         }
179                 if (zoom < -8) zoom = -8;
180                 }
181         else
182                 {
183                 while (increment > 0)
184                         {
185                         zoom++;
186                         if (zoom == -1) zoom = 1;
187                         increment--;
188                         }
189                 if (zoom > 3) zoom = 3;
190                 }
191         if (zoom != imd->zoom)
192                 image_area_set_zoom(imd, zoom);
193 }
194
195 void image_area_set_zoom(ImageWindow *imd, gint zoom)
196 {
197         if (zoom == imd->zoom && imd->width > 0 && imd->height > 0) return;
198
199         imd->zoom = zoom;
200         image_area_recalc_size(imd, NULL);
201
202         gtk_widget_set_usize (imd->table, imd->width, imd->height);
203         gtk_drawing_area_size(GTK_DRAWING_AREA(imd->image), imd->width, imd->height);
204 }
205
206 static void image_area_recalc_size(ImageWindow *imd, GtkAllocation *allocation)
207 {
208         gint w, h, ww, wh;
209         gfloat scale_factor = 1;
210
211         w = imd->image_data->rgb_width;
212         h = imd->image_data->rgb_height;
213         if (allocation)
214                 {
215                 ww = allocation->width;
216                 wh = allocation->height;
217                 }
218         else
219                 {
220                 ww = (imd->eventbox)->allocation.width;
221                 wh = (imd->eventbox)->allocation.height;
222                 }
223
224         if (imd == normal_image)
225                 {
226                 /* account for frame */
227                 ww -= 4;
228                 wh -= 4;
229                 }
230
231         if (imd->zoom == 0) /* zoom to fit */
232                 {
233                 if (imd == normal_image && imd->width == 0 && imd->height == 0 &&
234                     fit_window && toolwindow)
235                         {
236                         if (limit_window_size)
237                                 {
238                                 ww = (gdk_screen_width() * max_window_size / 100) - 4;
239                                 wh = (gdk_screen_height() * max_window_size / 100) - 4;
240                                 }
241                         else
242                                 {
243                                 ww = w;
244                                 wh = h;
245                                 }
246                         }
247                 if (w > ww || h > wh)
248                         {
249                         if ((gfloat)ww / w > (gfloat)wh / h)
250                                 {
251                                 scale_factor = (gfloat) wh / h;
252                                 h = wh;
253                                 w = w * scale_factor + 0.5;
254                                 if (w > ww) w = ww;
255                                 }
256                         else
257                                 {
258                                 scale_factor = (gfloat)ww / w;
259                                 w = ww;
260                                 h = h * scale_factor + 0.5;
261                                 if (h > wh) h = wh;
262                                 }
263                         if (w < 1) w = 1;
264                         if (h < 1) h = 1;
265                         }
266                 }
267         else if (imd->zoom > 0) /* zoom orig, in */
268                 {
269                 scale_factor = imd->zoom;
270                 w = w * scale_factor;
271                 h = h * scale_factor;
272                 }
273         else if (imd->zoom < -1) /* zoom out */
274                 {
275                 scale_factor = (- imd->zoom);
276                 w = w / scale_factor;
277                 h = h / scale_factor;
278                 }
279
280         imd->width = w;
281         imd->height = h;
282
283         if (debug) printf("recalc %d x %d @ %f\n", w, h, scale_factor);
284
285         if (imd->zoom_label)
286                 {
287                 set_zoom_label(imd->zoom_label, imd->zoom, scale_factor);
288                 }
289
290 /* this is causing problems with resizing
291         if (imd->top_window && imd->show_title_zoom)
292                 {
293                 gchar *buf = zoom_as_text(imd->zoom, scale_factor);
294                 gchar *zbuf = g_strconcat(" [ ", buf, "]", NULL);
295                 g_free(buf);
296                 set_window_title(imd, zbuf);
297                 g_free(zbuf);
298                 }
299 */
300
301         if (image_area_size_top_window(imd, w, h))
302                 {
303                 /* this is hacky */
304                 imd->artificial_size = TRUE;
305                 gtk_grab_add (info_zoom);
306                 while(gtk_events_pending()) gtk_main_iteration();
307                 gtk_grab_remove(info_zoom);
308                 imd->artificial_size = FALSE;
309                 }
310 }
311
312 /*
313  *-----------------------------------------------------------------------------
314  * image widget set/get image information
315  *-----------------------------------------------------------------------------
316  */ 
317
318 void image_area_set_path(ImageWindow *imd, gchar *newpath)
319 {
320         if (!imd->image_path || !newpath) return;
321
322         g_free(imd->image_path);
323         imd->image_path = g_strdup(newpath);
324         imd->image_name = filename_from_path(imd->image_path);
325
326         if (imd->top_window)
327                 {
328                 set_window_title(imd, NULL);
329                 }
330 }
331
332 gchar *image_area_get_path(ImageWindow *imd)
333 {
334         return imd->image_path;
335 }
336
337 gchar *image_area_get_name(ImageWindow *imd)
338 {
339         return imd->image_name;
340 }
341
342 void image_area_set_image(ImageWindow *imd, gchar *path, gint zoom)
343 {
344         if (path && imd->image_path && !strcmp(path, imd->image_path)) return;
345
346         g_free(imd->image_path);
347         if (path)
348                 {
349                 imd->image_path = g_strdup(path);
350                 imd->image_name = filename_from_path(imd->image_path);
351                 }
352         else
353                 {
354                 imd->image_path = NULL;
355                 imd->image_name = " ";
356                 zoom = 1;
357                 }
358
359         if (imd->image_data) gdk_imlib_destroy_image(imd->image_data);
360         if (path && isfile(path))
361                 {
362                 imd->image_data = gdk_imlib_load_image(path);
363                 if (!imd->image_data)
364                         {
365                         imd->image_data = gdk_imlib_create_image_from_xpm_data((gchar **)img_unknown_xpm);
366                         imd->unknown = TRUE;
367                         }
368                 else
369                         {
370                         imd->unknown = FALSE;
371                         }
372                 imd->size = filesize(path);
373                 }
374         else
375                 {
376                 if (path)
377                         imd->image_data = gdk_imlib_create_image_from_xpm_data((gchar **)img_unknown_xpm);
378                 else
379                         imd->image_data = gdk_imlib_create_image_from_data((char *)logo, NULL, logo_width, logo_height);
380                 imd->unknown = TRUE;
381                 imd->size = 0;
382                 }
383
384         imd->width = imd->old_width = 0;
385         imd->height = imd->old_height = 0;
386
387         if (imd->top_window)
388                 {
389                 set_window_title(imd, NULL);
390                 }
391         if (imd->info_label)
392                 {
393                 set_info_label(imd->info_label, imd->image_data->rgb_width, imd->image_data->rgb_height, imd->size, imd->unknown);
394                 }
395
396         /* do info area updates here */
397
398         imd->new_img = TRUE;
399         image_area_set_zoom(imd, zoom);
400 }
401
402 /*
403  *-----------------------------------------------------------------------------
404  * image widget redraw/callbacks (private)
405  *-----------------------------------------------------------------------------
406  */ 
407
408 static void image_area_redraw(ImageWindow *imd)
409 {
410         GdkBitmap *mask = NULL;
411
412         if (debug) printf("redrawn %d x %d\n", imd->width, imd->height);
413
414         if (!imd->image_data) return;
415
416         if (imd->width == imd->old_width && imd->height == imd->old_height)
417                 {
418                 if (debug) printf("redraw cancelled\n");
419                 return;
420                 }
421
422         if (imd->image_pixmap) gdk_imlib_free_pixmap(imd->image_pixmap);
423         imd->image_pixmap = NULL;
424
425         gdk_imlib_render(imd->image_data, imd->width, imd->height);
426         imd->image_pixmap = gdk_imlib_move_image(imd->image_data);
427         mask = gdk_imlib_move_mask(imd->image_data);
428
429         gdk_window_set_back_pixmap(imd->image->window, imd->image_pixmap, FALSE);
430         gdk_window_shape_combine_mask (imd->image->window, mask, 0, 0);
431         gdk_window_clear(imd->image->window);
432         gdk_flush();
433
434         imd->old_width = imd->width;
435         imd->old_height = imd->height;
436 }
437
438 static gint image_area_size_cb(GtkWidget *widget, GtkAllocation *allocation, gpointer data)
439 {
440         ImageWindow *imd = data;
441         gint old_w, old_h;
442         GtkAdjustment *h;
443         GtkAdjustment *v;
444         gfloat h_pos;
445         gfloat v_pos;
446         gfloat h_max;
447         gfloat v_max;
448
449         if (imd->artificial_size) return FALSE;
450
451         h = gtk_viewport_get_hadjustment(GTK_VIEWPORT(imd->viewport));
452         v = gtk_viewport_get_vadjustment(GTK_VIEWPORT(imd->viewport));
453
454         h_pos = h->value;
455         h_max = allocation->width;
456         v_pos = v->value;
457         v_max = allocation->height;
458
459         if (imd == normal_image)
460                 {
461                 h_max -= 4.0;
462                 v_max -= 4.0;
463                 }
464
465         if (h_pos > h->upper - h_max) h_pos = h->upper - h_max;
466         if (v_pos > v->upper - v_max) v_pos = v->upper - v_max;
467
468         if (imd->new_img)
469                 {
470                 imd->new_img = FALSE;
471                 gtk_adjustment_clamp_page(h, 0.0, h_max);
472                 gtk_adjustment_clamp_page(v, 0.0, v_max);
473                 }
474         else
475                 {
476                 gtk_adjustment_clamp_page(h, h_pos, h_max);
477                 gtk_adjustment_clamp_page(v, v_pos, v_max);
478                 }
479
480         gtk_adjustment_changed(h);
481         gtk_adjustment_changed(v);
482
483         if (!imd->image_data || imd->zoom != 0) return FALSE;
484
485         old_w = imd->width;
486         old_h = imd->height;
487         image_area_recalc_size(imd, allocation);
488         if (old_w != imd->width || old_h != imd->height)
489                 {
490                 gtk_widget_set_usize (imd->table, imd->width, imd->height);
491                 gtk_drawing_area_size(GTK_DRAWING_AREA(imd->image), imd->width, imd->height);
492                 }
493
494         if (debug) printf("sized %d x %d (%d x %d)\n", allocation->width, allocation->height, imd->width, imd->height);
495
496         return FALSE;
497 }
498
499 static gint image_area_update_cb(GtkWidget *widget, GdkEventConfigure *event, gpointer data)
500 {
501         ImageWindow *imd = data;
502
503         if (imd->artificial_size) return FALSE;
504
505         image_area_redraw(imd);
506
507         return FALSE;
508 }
509
510 /*
511  *-----------------------------------------------------------------------------
512  * image widget mouse routines (private)
513  *-----------------------------------------------------------------------------
514  */ 
515
516 static void set_mouse_cursor (GdkWindow *window, gint icon)
517 {
518         GdkCursor *cursor;
519
520         if (icon == -1)
521                 {
522                 cursor = NULL;
523                 }
524         else
525                 {
526                 cursor = gdk_cursor_new (icon);
527                 }
528
529         gdk_window_set_cursor (window, cursor);
530
531         if (cursor) gdk_cursor_destroy (cursor);
532 }
533
534 static void image_area_mouse_moved(GtkWidget *widget, GdkEventButton *bevent, gpointer data)
535 {
536         ImageWindow *imd = data;
537         GtkAdjustment* h;
538         GtkAdjustment* v;
539         gfloat x, y;
540         gfloat val;
541
542         if (!imd->in_drag || !gdk_pointer_is_grabbed()) return;
543
544         if (imd->drag_moved < 4)
545                 {
546                 imd->drag_moved++;
547                 }
548         else
549                 {
550                 set_mouse_cursor (imd->eventbox->window, GDK_FLEUR);
551                 }
552
553         h = gtk_viewport_get_hadjustment(GTK_VIEWPORT(imd->viewport));
554         v = gtk_viewport_get_vadjustment(GTK_VIEWPORT(imd->viewport));
555
556         x = imd->drag_last_x - bevent->x;
557         y = imd->drag_last_y - bevent->y;
558
559         /* x */
560         if (h->upper - h->page_size > 0)
561                 {
562                 val = (float)h->value + x;
563                 if (val < 0 ) val = 0;
564                 if (val > h->upper - h->page_size) val = h->upper - h->page_size;
565                 h->value = val;
566                 gtk_adjustment_set_value (GTK_ADJUSTMENT(h), val);
567                 }
568
569         /* y */
570         if (v->upper - v->page_size > 0)
571                 {
572                 val = v->value + y;
573                 if (val < 0 ) val = 0;
574                 if (val > v->upper - v->page_size) val = v->upper - v->page_size;
575                 v->value = val;
576                 gtk_adjustment_set_value (GTK_ADJUSTMENT(v), val);
577                 }
578
579         gtk_adjustment_value_changed(h);
580         gtk_adjustment_value_changed(v);
581
582         imd->drag_last_x = bevent->x;
583         imd->drag_last_y = bevent->y;
584 }
585
586 static void image_area_mouse_pressed(GtkWidget *widget, GdkEventButton *bevent, gpointer data)
587 {
588         ImageWindow *imd = data;
589         switch (bevent->button)
590                 {
591                 case 1:
592                         imd->in_drag = TRUE;
593                         imd->drag_last_x = bevent->x;
594                         imd->drag_last_y = bevent->y;
595                         imd->drag_moved = 0;
596                         gdk_pointer_grab (imd->eventbox->window, FALSE,
597                                 GDK_POINTER_MOTION_MASK |
598                                 GDK_BUTTON_RELEASE_MASK,
599                                 NULL, NULL, bevent->time);
600                         gtk_grab_add (imd->eventbox);
601                         break;
602                 case 2:
603                         imd->drag_moved = 0;
604                         break;
605                 case 3:
606                         if (imd->func_btn3)
607                                 imd->func_btn3(imd, bevent, imd->data_btn3);
608                         break;
609                 default:
610                         break;
611                 }
612         gtk_widget_grab_focus(imd->viewport);
613 }
614
615 static void image_area_mouse_released(GtkWidget *widget, GdkEventButton *bevent, gpointer data)
616 {
617         ImageWindow *imd = data;
618         if (gdk_pointer_is_grabbed() && GTK_WIDGET_HAS_GRAB (imd->eventbox))
619                 {
620                 gtk_grab_remove (imd->eventbox);
621                 gdk_pointer_ungrab (bevent->time);
622                 set_mouse_cursor (imd->eventbox->window, -1);
623                 }
624
625         if (bevent->button == 1)
626                 {
627                 if (imd->drag_moved < 4 && imd->func_btn1)
628                         imd->func_btn1(imd, bevent, imd->data_btn1);
629                 }
630
631         if (bevent->button == 2)
632                 {
633                 if (imd->drag_moved < 4 && imd->func_btn2)
634                         imd->func_btn2(imd, bevent, imd->data_btn2);
635                 }
636
637         imd->in_drag = FALSE;
638 }
639
640 static void image_area_mouse_drag(GtkWidget *widget, GdkDragContext *context, gpointer data)
641 {
642         ImageWindow *imd = data;
643         imd->drag_moved = 4;
644 }
645
646 /*
647  *-----------------------------------------------------------------------------
648  * image widget setup routines
649  *-----------------------------------------------------------------------------
650  */ 
651
652 void image_area_set_topwindow(ImageWindow *imd, GtkWidget *window, gchar *title, gint show_zoom)
653 {
654         imd->top_window = window;
655         imd->show_title_zoom = show_zoom;
656
657         g_free(imd->title);
658         if (title)
659                 imd->title = g_strdup(title);
660         else
661                 imd->title = NULL;
662 }
663
664 void image_area_set_labels(ImageWindow *imd, GtkWidget *info, GtkWidget *zoom)
665 {
666         imd->info_label = info;
667         imd->zoom_label = zoom;
668 }
669
670 void image_area_set_button(ImageWindow *imd, gint button,
671         void (*func)(ImageWindow *, GdkEventButton *, gpointer), gpointer data)
672 {
673         switch (button)
674                 {
675                 case 1:
676                         imd->func_btn1 = func;
677                         imd->data_btn1 = data;
678                         break;
679                 case 2:
680                         imd->func_btn2 = func;
681                         imd->data_btn2 = data;
682                         break;
683                 case 3:
684                         imd->func_btn3 = func;
685                         imd->data_btn3 = data;
686                         break;
687                 }
688 }
689
690 ImageWindow *image_area_new(GtkWidget *top_window)
691 {
692         GtkObject *h_adj;
693         GtkObject *v_adj;
694         ImageWindow *imd;
695
696         imd = g_new0(ImageWindow, 1);
697         imd->zoom = 0;
698
699         imd->top_window = top_window;
700         imd->title = g_strdup("GQview - ");
701         imd->show_title_zoom = FALSE;
702         imd->new_img = FALSE;
703
704         imd->eventbox = gtk_event_box_new();
705
706         gtk_signal_connect(GTK_OBJECT(imd->eventbox),"motion_notify_event",
707                            GTK_SIGNAL_FUNC(image_area_mouse_moved), imd);
708         gtk_signal_connect(GTK_OBJECT(imd->eventbox),"button_press_event",
709                            GTK_SIGNAL_FUNC(image_area_mouse_pressed), imd);
710         gtk_signal_connect(GTK_OBJECT(imd->eventbox),"button_release_event",
711                            GTK_SIGNAL_FUNC(image_area_mouse_released), imd);
712         gtk_widget_set_events(imd->eventbox, GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK);
713
714         /* viewer */
715         h_adj = gtk_adjustment_new(0.0,0.0,0.0,1.0,1.0,1.0);
716         v_adj = gtk_adjustment_new(0.0,0.0,0.0,1.0,1.0,1.0);
717
718         imd->viewport = gtk_viewport_new (GTK_ADJUSTMENT(h_adj), GTK_ADJUSTMENT(v_adj));
719         gtk_container_add(GTK_CONTAINER(imd->eventbox), imd->viewport);
720
721         /* table for resize */
722         imd->table = gtk_table_new (1,1,TRUE);
723         gtk_container_add(GTK_CONTAINER (imd->viewport), imd->table);
724
725         /* imagewindow */
726         imd->image = gtk_drawing_area_new();
727         gtk_table_attach(GTK_TABLE (imd->table),imd->image,0,1,0,1,GTK_EXPAND,GTK_EXPAND,0,0);
728
729         gtk_signal_connect(GTK_OBJECT(imd->eventbox),"size_allocate",GTK_SIGNAL_FUNC(image_area_size_cb), imd);
730         gtk_signal_connect(GTK_OBJECT(imd->image),"configure_event",GTK_SIGNAL_FUNC(image_area_update_cb), imd);
731
732         gtk_signal_connect(GTK_OBJECT(imd->viewport),"drag_begin",
733                            GTK_SIGNAL_FUNC(image_area_mouse_drag), imd);
734
735         return imd;
736 }
737
738 void image_area_free(ImageWindow *imd)
739 {
740         g_free(imd->image_path);
741         g_free(imd->title);
742
743         if (imd->image_pixmap) gdk_imlib_free_pixmap(imd->image_pixmap);
744         if (imd->image_data) gdk_imlib_destroy_image(imd->image_data);
745
746         g_free(imd);
747 }
748
749 gint get_default_zoom(ImageWindow *imd)
750 {
751         gint zoom;
752
753         if (zoom_mode == ZOOM_RESET_ORIGINAL)
754                 {
755                 zoom = 1;
756                 }
757         else if (zoom_mode == ZOOM_RESET_FIT_WINDOW)
758                 {
759                 zoom = 0;
760                 }
761         else
762                 {
763                 if (imd)
764                         {
765                         zoom = image_area_get_zoom(imd);
766                         }
767                 else
768                         {
769                         zoom = 1;
770                         }
771                 }
772
773         return zoom;
774 }
775
776 /*
777  *-----------------------------------------------------------------------------
778  * image widget misc utils
779  *-----------------------------------------------------------------------------
780  */ 
781
782 void image_area_to_root(ImageWindow *imd, gint scaled)
783 {                                                                               
784         GdkVisual *gdkvisual;
785         GdkWindow *rootwindow;
786         GdkPixmap *pixmap;
787
788         if (!imd || !imd->image_data) return;
789
790
791         rootwindow = (GdkWindow *) &gdk_root_parent;    /* hmm, don't know, correct? */
792         gdkvisual = gdk_window_get_visual(rootwindow);
793         if (gdkvisual != gdk_imlib_get_visual()) return;
794
795         if (scaled)
796                 {
797                 gdk_imlib_render(imd->image_data, gdk_screen_width(), gdk_screen_height());
798                 }
799         else
800                 {
801                 gdk_imlib_render(imd->image_data, imd->width, imd->height);
802                 }
803
804         pixmap = gdk_imlib_move_image(imd->image_data);
805         gdk_window_set_back_pixmap(rootwindow, pixmap, FALSE);
806         gdk_window_clear(rootwindow);
807         gdk_imlib_free_pixmap(pixmap);
808
809         gdk_flush();
810 }
811
812