1 /* Hey EMACS -*- linux-c -*- */
2 /* $Id: calc.c 2729 2007-12-16 15:29:16Z roms $ */
3
4 /* TiEmu - Tiemu Is an EMUlator
5 *
6 * Copyright (c) 2000-2001, Thomas Corvazier, Romain Lievin
7 * Copyright (c) 2001-2003, Romain Lievin
8 * Copyright (c) 2003, Julien Blache
9 * Copyright (c) 2004, Romain Li�vin
10 * Copyright (c) 2005, Romain Li�vin
11 * Copyright (c) 2005, Julien Blache
12 * Copyright (c) 2006, Kevin Kofler
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
27 */
28
29 #ifdef HAVE_CONFIG_H
30 # include <config.h>
31 #endif /* */
32
33 #ifdef __WIN32__
34 #include <io.h>
35 #endif
36 #include <stdlib.h>
37 #include <string.h>
38 #include <gtk/gtk.h>
39 #include <glade/glade.h>
40 #include <gdk-pixbuf/gdk-pixbuf.h>
41
42 #include "intl.h"
43 #include "paths.h"
44 #include "skinops.h"
45 #include "support.h"
46 #include "ti68k_int.h"
47 #include "struct.h"
48 #include "tie_error.h"
49 #include "calc.h"
50 #include "dbg_all.h"
51 #include "screenshot.h"
52 #include "keymap.h"
53 #include "logging.h"
54 #include "gscales.h"
55
56 #define ALLOW_RESIZE_WIN32
57
58 GtkWidget *main_wnd = NULL;
59 gboolean explicit_destroy = 0;
60 GtkWidget *area = NULL;
61
62 SKIN_INFOS skin_infos = { 0 };
63
64 extern GdkPixbuf* lcd_mem;
65 extern GdkPixbuf* lcd;
66 extern GdkPixmap* pixmap;
67
68 extern Pc2TiKey* kbd_keymap;
69 extern const char* skn_keymap;
70 extern const char sknKey92[];
71 extern const char sknKey89[];
72
73 extern uint32_t* lcd_bytmap;
74
75 extern LCD_INFOS li;
76 extern float sf; // scaling factor
77
78 extern LCD_RECT ls;
79 extern LCD_RECT lr;
80 extern SKN_RECT sr;
81 extern WND_RECT wr;
82
83 static guint tid = -1;
84
85 extern int shot_cnt;
86 extern int skip_cnt;
87
88 // part 1: set scale factor
set_scale(int view_mode)89 static void set_scale(int view_mode)
90 {
91 if(view_mode == VIEW_NORMAL)
92 {
93 options.scale = sf = 1.0;
94 }
95 else if(view_mode == VIEW_LARGE)
96 {
97 options.scale = sf = 2.0;
98 }
99 else if(view_mode == VIEW_FULL)
100 {
101 GdkScreen* screen = gdk_screen_get_default();
102 gint sw = gdk_screen_get_width(screen);
103 gint sh = gdk_screen_get_height(screen);
104
105 sf = (float)sw / lr.w;
106 sf = (float)sh / lr.h;
107 //printf("%i %i %f\n", sw, lr.w, sf);
108 //printf("%i %i %f\n", sh, lr.h, sf);
109
110 options.scale = sf = (float)1.0; // restricted to 3.0, too CPU intensive !
111 }
112 }
113
114 // part 2: compute sizes
set_infos(void)115 static void set_infos(void) // set window & lcd sizes
116 {
117 // LCD rectangle (source: skin)
118 ls.x = (int)(sf * skin_infos.lcd_pos.left);
119 ls.y = (int)(sf * skin_infos.lcd_pos.top);
120 ls.w = (int)(sf * tihw.lcd_w);
121 ls.h = (int)(sf * tihw.lcd_h);
122
123 // LCD rectangle (target: window)
124 if(options.skin)
125 {
126 lr.x = ls.x;
127 lr.y = ls.y;
128 }
129 else
130 {
131 lr.x = 0;
132 lr.y = 0;
133 }
134 lr.w = (int)(sf * tihw.lcd_w);
135 lr.h = (int)(sf * tihw.lcd_h);
136
137
138 // SKN rectangle
139 sr.x = sr.y = 0;
140 sr.w = (int)(sf * skin_infos.width);
141 sr.h = (int)(sf * skin_infos.height);
142
143 // WND rectangle (= LCD or SKN depending on w/ or w/o skin)
144 wr.x = wr.y = 0;
145 if(options.skin)
146 {
147 wr.w = sr.w;
148 wr.h = sr.h;
149 }
150 else
151 {
152 wr.w = lr.w;
153 wr.h = lr.h;
154 }
155
156 #if 0
157 printf("LCD src: %3i %3i %3i %3i\n", ls.x, ls.y, ls.w, ls.h);
158 printf("LCD dst: %3i %3i %3i %3i\n", lr.x, lr.y, lr.w, lr.h);
159 printf("SKN : %3i %3i %3i %3i\n", sr.x, sr.y, sr.w, sr.h);
160 printf("WND : %3i %3i %3i %3i\n", wr.x, wr.y, wr.w, wr.h);
161 #endif
162 }
163
164 // part 3: set changes on window
set_window(int full_redraw)165 static void set_window(int full_redraw)
166 {
167 if(main_wnd->window == NULL)
168 return;
169
170 // resize window and drawing area
171 if(full_redraw)
172 gtk_window_resize(GTK_WINDOW(main_wnd), wr.w, wr.h);
173
174 #if defined(__WIN32__) && defined(ALLOW_RESIZE_WIN32)
175 if(!full_redraw)
176 gdk_window_resize(main_wnd->window, wr.w, wr.h);
177 #endif
178
179 // reallocate backing pixmap
180 if(pixmap != NULL)
181 {
182 // free current backing pixmap
183 g_object_unref(pixmap);
184 pixmap = NULL;
185
186 // and allocate a new one
187 pixmap = gdk_pixmap_new(main_wnd->window, wr.w, wr.h, -1);
188 if(pixmap == NULL)
189 {
190 gchar *s = g_strdup_printf("unable to create backing pixmap.\n");
191 tiemu_error(0, s);
192 g_free(s);
193 return;
194 }
195 }
196 }
197
set_constraints(void)198 static void set_constraints(void)
199 {
200 // Allows resizing of window with a constant aspect ratio.
201 // This is the right way as used under Linux.
202 // Does not work under Windows thus not enabled.
203
204 #if !defined(__WIN32__) || !defined(ALLOW_RESIZE_WIN32)
205 if(1)
206 {
207 GdkGeometry geom = { -1 };
208 GdkWindowHints mask = GDK_HINT_MIN_SIZE | GDK_HINT_ASPECT;
209 double r = (float)wr.w / wr.h;
210
211 geom.min_width = 100;
212 geom.min_height = 100;
213
214 geom.min_aspect = r;
215 geom.max_aspect = r;
216 gtk_window_set_geometry_hints(GTK_WINDOW(main_wnd),
217 area, &geom, mask);
218
219 //printf("set_constraints: %i %i %1.2f\n", wr.w, wr.h, r);
220 }
221 #endif
222 }
223
224 // Main wnd by loading glade xml file or by executing glade generated code
display_main_wnd(void)225 gint display_main_wnd(void)
226 {
227 GladeXML *xml;
228 gchar *title;
229
230 xml = glade_xml_new
231 (tilp_paths_build_glade("calc-2.glade"), "calc_wnd",
232 PACKAGE);
233 if (!xml)
234 g_error(_("%s: GUI loading failed!\n"), __FILE__);
235 glade_xml_signal_autoconnect(xml);
236
237 main_wnd = glade_xml_get_widget(xml, "calc_wnd");
238 area = glade_xml_get_widget(xml, "drawingarea1");
239
240 gtk_window_move(GTK_WINDOW(main_wnd), options3.calc.rect.x, options3.calc.rect.y);
241 set_constraints();
242 gtk_widget_realize(main_wnd); // set drawing area valid
243
244 // set window title (useful for TIGCC-IDE for instance)
245 // Note: lpWindowName is "TiEmu (%s)" and lpClassName is "gdkWindowToplevel"
246 title = g_strdup_printf("TiEmu (%s)", ti68k_calctype_to_string(tihw.calc_type));
247 gtk_window_set_title(GTK_WINDOW(main_wnd), title);
248 g_free(title);
249
250 return 0;
251 }
252
253 extern void on_exit_without_saving_state1_activate(GtkMenuItem* item, gpointer data);
254
255 GLADE_CB void
on_calc_wnd_destroy(GtkObject * object,gpointer user_data)256 on_calc_wnd_destroy (GtkObject *object,
257 gpointer user_data)
258 {
259 // Uninstall LCD refresh (to avoid earlier use of main_wnd by hid_lcd_update)
260 g_source_remove(tid);
261
262 // When GTK called this signal, the widget has already been destroy
263 // thus set the pointer to a valid value, ie NULL .
264 main_wnd = NULL;
265
266 if(!explicit_destroy)
267 on_exit_without_saving_state1_activate(NULL, NULL);
268 }
269
270 extern void redraw_skin(void);
271
272 GLADE_CB gboolean
on_drawingarea1_configure_event(GtkWidget * widget,GdkEventConfigure * event,gpointer user_data)273 on_drawingarea1_configure_event (GtkWidget *widget,
274 GdkEventConfigure *event,
275 gpointer user_data)
276 {
277 float factor;
278
279 // compute scaling factor
280 if(options.skin)
281 factor = (float)event->width / (float)skin_infos.width;
282 else
283 factor = (float)event->width / (float)tihw.lcd_w;
284
285 #if 0
286 printf("on_drawingarea1_configure_event: x y w h = %i %i %i %i\n",
287 event->x, event->y, event->width, event->height);
288 printf("on_drawingarea1_configure_event: f = %1.2f\n", factor);
289 #endif
290
291 // if normal or large view then exits
292 if((factor == 1.0) || (factor == 2.0))
293 return FALSE;
294
295 // set scaling factor
296 options.scale = sf = factor;
297 options.view = VIEW_CUSTOM;
298
299 // compute sizes
300 set_infos();
301
302 // and set window size
303 set_window(0);
304 redraw_skin();
305
306 return FALSE;
307 }
308
309 GLADE_CB gboolean
on_drawingarea1_expose_event(GtkWidget * widget,GdkEventExpose * event,gpointer user_data)310 on_drawingarea1_expose_event (GtkWidget *widget,
311 GdkEventExpose *event,
312 gpointer user_data)
313 {
314 gdk_draw_pixmap(
315 widget->window,
316 widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
317 pixmap,
318 event->area.x, event->area.y,
319 event->area.x, event->area.y,
320 event->area.width, event->area.height);
321
322 return FALSE;
323 }
324
match_skin(int calc_type)325 static int match_skin(int calc_type)
326 {
327 SKIN_INFOS *sk = &skin_infos;
328 int ok;
329 gchar *skin_name, *s;
330
331 s = g_strdup(ti68k_calctype_to_string(calc_type));
332 skin_name = g_ascii_strdown(s, strlen(s));
333 g_free(s);
334
335 if(!strcmp(skin_name, "ti92+"))
336 skin_name[4] = '\0';
337
338 #ifdef __IPAQ__
339 s = g_strconcat("ipaq_", skin_name, NULL);
340 g_free(skin_name);
341 skin_name = s;
342 #endif
343
344 // filename is "", load default skin
345 if(!strcmp(g_basename(options.skin_file), ""))
346 {
347 g_free(options.skin_file);
348 options.skin_file = g_strdup_printf("%s%s.skn",
349 inst_paths.skin_dir, skin_name);
350 g_free(skin_name);
351 return -1;
352 }
353
354 // load skin header
355 if(skin_read_header(sk, options.skin_file) == -1)
356 {
357 g_free(options.skin_file);
358 options.skin_file = g_strdup_printf("%s%s.skn",
359 inst_paths.skin_dir, skin_name);
360 g_free(skin_name);
361 return -1;
362 }
363
364 // is skin compatible
365 switch(tihw.calc_type)
366 {
367 case TI92:
368 case TI92p:
369 ok = !strcmp((const char *)sk->calc, SKIN_TI92) || !strcmp((const char *)sk->calc, SKIN_TI92P);
370 break;
371 case TI89:
372 ok = !strcmp((const char *)sk->calc, SKIN_TI89);
373 break;
374 case TI89t:
375 ok = !strcmp((const char *)sk->calc, SKIN_TI89T);
376 break;
377 case V200:
378 ok = !strcmp((const char *)sk->calc, SKIN_V200);
379 break;
380 default:
381 ok = 0;
382 break;
383 }
384
385 if(!ok)
386 {
387 g_free(options.skin_file);
388 options.skin_file = g_strdup_printf("%s%s.skn",
389 inst_paths.skin_dir, skin_name);
390
391 //tiemu_error(0, _("skin incompatible with the current calc model. Falling back to default skin."));
392 g_free(skin_name);
393 return -1;
394 }
395
396 g_free(skin_name);
397 return 0;
398 }
399
match_keymap(int calc_type)400 static int match_keymap(int calc_type)
401 {
402 gchar *keys_name, *s;
403 int ct, ok;
404
405 s = g_strdup(ti68k_calctype_to_string(calc_type));
406 keys_name = g_ascii_strdown(s, strlen(s));
407
408 if(!strcmp(keys_name, "ti92+") || !strcmp(keys_name, "ti89t"))
409 keys_name[4] = '\0';
410 if(!strcmp(keys_name, "v200plt"))
411 strcpy(keys_name, "ti92");
412
413 // filename is "", load default keymap
414 if(!strcmp(g_basename(options.keys_file), ""))
415 {
416 g_free(options.keys_file);
417 options.keys_file = g_strdup_printf("%s%s.map",
418 inst_paths.skin_dir, keys_name);
419 }
420
421 // load keymap header
422 ct = keymap_read_header(options.keys_file);
423 if(ct == -1)
424 {
425 g_free(options.keys_file);
426 options.keys_file = g_strdup_printf("%s%s.map",
427 inst_paths.skin_dir, keys_name);
428 g_free(keys_name);
429 return -1;
430 }
431
432 // is keymap compatible
433 switch(tihw.calc_type)
434 {
435 case TI92:
436 case TI92p:
437 case V200:
438 ok = (ct == TI92) || (ct == TI92p) || (ct == V200);
439 break;
440 case TI89:
441 case TI89t:
442 ok = (ct == TI89) || (ct == TI89t);
443 break;
444 default:
445 ok = 0;
446 break;
447 }
448
449 if(!ok)
450 {
451 g_free(options.keys_file);
452 options.keys_file = g_strdup_printf("%s%s.map",
453 inst_paths.skin_dir, keys_name);
454
455 //tiemu_error(0, _("keymap incompatible with the current calc model. Falling back to default keymap."));
456 g_free(keys_name);
457 return -1;
458 }
459
460 g_free(keys_name);
461 return 0;
462 }
463
464 G_LOCK_EXTERN(lcd_flag);
465 extern volatile int lcd_flag;
466 extern volatile int debugger;
467
hid_refresh(gpointer data)468 static gint hid_refresh (gpointer data)
469 {
470 if(lcd_flag || (tihw.hw_type >= HW2))
471 {
472 // TI92+: jackycar, TI89: baballe
473 hid_update_lcd();
474 G_LOCK(lcd_flag);
475 lcd_flag = 0;
476 G_UNLOCK(lcd_flag);
477
478 if(tihw.hw_type >= HW2)
479 lcd_hook_hw2(TRUE);
480 }
481
482 return TRUE;
483 }
484
485 void compute_convtable(void);
486 void compute_grayscale(void);
487
488 extern void dnd_init(void);
489 extern void dnd_exit(void);
490
hid_init(void)491 int hid_init(void)
492 {
493 // Found a PC keyboard keymap
494 match_keymap(tihw.calc_type);
495
496 // Load kbd keymap
497 if(keymap_load(options.keys_file) == -1)
498 {
499 gchar *s = g_strdup_printf("unable to load this keymap: <%s>\n", options.keys_file);
500 tiemu_error(0, s);
501 g_free(s);
502 return -1;
503 }
504
505 // Found a skin
506 match_skin(tihw.calc_type);
507
508 // Load skin (2 parts)
509 if(skin_load(&skin_infos, options.skin_file) == -1)
510 {
511 gchar *s = g_strdup_printf("unable to load this skin: <%s>\n", options.skin_file);
512 tiemu_error(0, s);
513 g_free(s);
514 return -1;
515 }
516
517 // Set skin keymap depending on calculator type
518 switch(tihw.calc_type)
519 {
520 case TI92:
521 case TI92p:
522 case V200:
523 skn_keymap = sknKey92;
524 break;
525 case TI89:
526 case TI89t:
527 skn_keymap = sknKey89;
528 break;
529 default:
530 {
531 gchar *s = g_strdup_printf("no skin found for this calc\n");
532 tiemu_error(0, s);
533 g_free(s);
534 return -1;
535 }
536 }
537
538 // Set window/LCD sizes
539 sf = options.scale;
540 set_scale(options.view);
541 set_infos();
542
543 // Allocate the TI screen buffer
544 lcd_bytmap = (uint32_t *)malloc(LCDMEM_W * LCDMEM_H);
545
546 // Allocate the lcd pixbuf
547 lcd_mem = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, LCDMEM_W, LCDMEM_H);
548 if(lcd_mem == NULL)
549 {
550 gchar *s = g_strdup_printf("unable to create LCD pixbuf.\n");
551 tiemu_error(0, s);
552 g_free(s);
553 return -1;
554 }
555
556 // Used by TI89 (the LCD view is clipped from memory view)
557 lcd = gdk_pixbuf_new_subpixbuf(lcd_mem, 0, 0, tihw.lcd_w, tihw.lcd_h);
558
559 // Constants for LCD update (speed-up)
560 li.n_channels = gdk_pixbuf_get_n_channels (lcd_mem);
561 li.width = gdk_pixbuf_get_width (lcd_mem);
562 li.height = gdk_pixbuf_get_height (lcd_mem);
563 li.rowstride = gdk_pixbuf_get_rowstride (lcd_mem);
564 li.pixels = gdk_pixbuf_get_pixels (lcd_mem);
565
566 // Create main window
567 display_main_wnd();
568
569 // Allocate the backing pixmap (used for drawing and refresh)
570 pixmap = gdk_pixmap_new(main_wnd->window, wr.w, wr.h, -1);
571 if(pixmap == NULL)
572 {
573 gchar *s = g_strdup_printf("unable to create backing pixmap.\n");
574 tiemu_error(0, s);
575 g_free(s);
576 return -1;
577 }
578
579 // Draw the skin and compute grayscale palette
580 set_window(1);
581 redraw_skin();
582 compute_grayscale();
583
584 // Init the planar/chunky conversion table for LCD
585 compute_convtable();
586
587 // Install LCD refresh: 100 FPS (10 ms)
588 tid = g_timeout_add((params.lcd_rate == -1) ? 50 : params.lcd_rate,
589 (GtkFunction)hid_refresh, NULL);
590
591 explicit_destroy = 0;
592 gtk_widget_show(main_wnd); // show wnd here
593
594 if(options.view == VIEW_FULL)
595 gdk_window_fullscreen(main_wnd->window);
596
597 lcd_planes[0] = tihw.lcd_adr;
598 lcd_planebufs[0] = &tihw.ram[tihw.lcd_adr];
599 ngc = 1;
600 lcd_changed = 1;
601
602 dnd_init();
603
604 return 0;
605 }
606
hid_exit(void)607 int hid_exit(void)
608 {
609
610 // Uninstall LCD refresh
611 g_source_remove(tid);
612
613 // Release resources
614 if(lcd_mem != NULL)
615 {
616 g_object_unref(lcd_mem);
617 lcd_mem = NULL;
618 g_object_unref(lcd);
619 lcd = NULL;
620 }
621
622 if(pixmap != NULL)
623 {
624 g_object_unref(pixmap);
625 pixmap = NULL;
626 }
627
628 // Destroy window
629 if(main_wnd)
630 {
631 explicit_destroy = !0;
632 gtk_widget_destroy(main_wnd);
633 }
634
635 return 0;
636 }
637
hid_lcd_rate_set(void)638 void hid_lcd_rate_set(void)
639 {
640 g_source_remove(tid);
641
642 tid = g_timeout_add((params.lcd_rate == -1) ? 50 : params.lcd_rate,
643 (GtkFunction)hid_refresh, NULL);
644 }
645
hid_switch_with_skin(void)646 int hid_switch_with_skin(void)
647 {
648 options.skin = 1;
649 set_infos();
650 set_constraints();
651 set_window(1);
652 redraw_skin();
653
654 return 0;
655 }
656
hid_switch_without_skin(void)657 int hid_switch_without_skin(void)
658 {
659 options.skin = 0;
660 set_infos();
661 set_constraints();
662 set_window(1);
663 redraw_skin();
664
665 return 0;
666 }
667
hid_change_skin(const char * filename)668 int hid_change_skin(const char *filename)
669 {
670 int ret1, ret2;
671
672 ret1 = hid_exit();
673 ret2 = hid_init();
674
675 return ret1 | ret2;
676 }
677
hid_switch_fullscreen(void)678 int hid_switch_fullscreen(void)
679 {
680 if(options.view != VIEW_FULL)
681 {
682 set_scale(options.view = VIEW_FULL);
683 set_infos();
684 set_window(1);
685 redraw_skin();
686 gdk_window_fullscreen(main_wnd->window);
687 }
688
689 return 0;
690 }
691
hid_switch_normal_view(void)692 int hid_switch_normal_view(void)
693 {
694 if(options.view != VIEW_NORMAL)
695 {
696 set_scale(options.view = VIEW_NORMAL);
697 set_infos();
698 set_window(1);
699 redraw_skin();
700 gdk_window_unfullscreen(main_wnd->window);
701 }
702
703 return 0;
704 }
705
hid_switch_large_view(void)706 int hid_switch_large_view(void)
707 {
708 if(options.view != VIEW_LARGE)
709 {
710 set_scale(options.view = VIEW_LARGE);
711 set_infos();
712 set_window(1);
713 redraw_skin();
714 gdk_window_unfullscreen(main_wnd->window);
715 }
716
717 return 0;
718 }
719
hid_screenshot_burst(void)720 int hid_screenshot_burst(void)
721 {
722 shot_cnt = options2.shots;
723 skip_cnt = options2.skips;
724
725 return 0;
726 }
727
hid_screenshot_single(void)728 int hid_screenshot_single(void)
729 {
730 gchar *outfile;
731 gchar *ext = "";
732 gchar *type = "";
733
734 GdkPixbuf *pixbuf = { 0 };
735 gboolean result = FALSE;
736 GError *error = NULL;
737
738 switch(options2.format)
739 {
740 case IMG_JPG: ext = "jpg"; type = "jpeg"; break;
741 case IMG_PNG: ext = "png"; type = "png"; break;
742 case IMG_ICO: ext = "ico"; type = "ico"; break;
743 case IMG_EPS: ext = "eps"; type = "eps"; break;
744 case IMG_PDF: ext = "pdf"; type = "pdf"; break;
745 case IMG_BMP: ext = "bmp"; type = "bmp"; break;
746 default: ext = "png"; type = "png"; break;
747 }
748
749 outfile = g_strdup_printf("%s%s%s%03i.%s", options2.folder, G_DIR_SEPARATOR_S,
750 options2.file, options2.counter, ext);
751 tiemu_info(_("screenshot to %s... "), outfile);
752
753 if((options2.size == IMG_LCD) && (options2.type == IMG_BW))
754 {
755 // get pixbuf from TI memory (LCD buffer)
756 pixbuf = hid_copy_lcd();
757 }
758 else if((options2.size == IMG_LCD) && (options2.type == IMG_COL))
759 {
760 // get pixbuf from grayscale lcd
761 pixbuf = gdk_pixbuf_copy(lcd);
762 }
763 else if((options2.size == IMG_SKIN) && (options2.type == IMG_COL))
764 {
765 // get pixbuf from backing pixmap
766 pixbuf = gdk_pixbuf_get_from_drawable(NULL, pixmap, NULL, 0, 0, 0, 0, wr.w, wr.h);
767 }
768 else
769 {
770 tiemu_warning(_("unsupported screenshot options combination, screenshot aborted."));
771 return 0;
772 }
773
774 switch (options2.format)
775 {
776 case IMG_EPS:
777 result = tiemu_screen_write_eps(outfile, pixbuf, &error);
778 break;
779 case IMG_PDF:
780 result = tiemu_screen_write_pdf(outfile, pixbuf, &error);
781 break;
782 default:
783 result = gdk_pixbuf_save(pixbuf, outfile, type, &error, NULL);
784 break;
785 }
786
787 if(options2.clipboard)
788 {
789 GtkClipboard *clipboard;
790
791 clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
792 gtk_clipboard_set_image(clipboard, pixbuf);
793 }
794
795 if (result == FALSE)
796 {
797 tiemu_warning(_("failed to save pixbuf file: %s: %s"), outfile, error->message);
798 g_error_free(error);
799 }
800 g_object_unref(pixbuf);
801
802 tiemu_info(_("done!"));
803 options2.counter++;
804
805 return 0;
806 }
807
808 GLADE_CB gboolean
on_calc_wnd_window_state_event(GtkWidget * widget,GdkEvent * event,gpointer user_data)809 on_calc_wnd_window_state_event (GtkWidget *widget,
810 GdkEvent *event,
811 gpointer user_data)
812 {
813 return FALSE;
814 }
815