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