"Fossies" - the Fresh Open Source Software Archive 
Member "gamgi0.17.5x/src/io/gamgi_io_file.c" (23 Feb 2022, 25986 Bytes) of package /linux/misc/gamgi-all-0.17.5x.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.
For more information about "gamgi_io_file.c" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
0.17.4x_vs_0.17.5x.
1 /******************************************
2 *
3 * $GAMGI/src/io/gamgi_io_file.c
4 *
5 * Copyright (C) 2004 Carlos Pereira
6 *
7 * Distributed under the terms of the GNU
8 * General Public License: $GAMGI/LICENSE
9 *
10 */
11
12 #include "gamgi_engine.h"
13 #include "gamgi_gtk.h"
14 #include "gamgi_math.h"
15 #include "gamgi_expat.h"
16 #include "gamgi_io.h"
17 #include "gamgi_global.h"
18
19 #include "gamgi_engine_list.h"
20 #include "gamgi_engine_count.h"
21 #include "gamgi_engine_dlist.h"
22 #include "gamgi_gtk_dialog.h"
23 #include "gamgi_mesa_area.h"
24 #include "gamgi_expat_import.h"
25 #include "gamgi_expat_export.h"
26 #include "gamgi_io_socket.h"
27 #include "gamgi_io_token.h"
28 #include "gamgi_io_error.h"
29 #include "gamgi_io_xyz.h"
30
31 #include <fcntl.h>
32
33 static gamgi_bool static_tokens (char *string, char *tokens,
34 int n_tokens, gamgi_bool end)
35 {
36 gamgi_bool start;
37 char *substring;
38 int i, length = 0;
39
40 for (i = 0; i < n_tokens; i++)
41 {
42 if (tokens[0] == '\0') { start = TRUE; tokens++; }
43 else start = FALSE;
44
45 if ((substring = strstr (string, tokens)) == NULL) return FALSE;
46 if (start == FALSE && substring != string) return FALSE;
47
48 length = strlen (tokens);
49 string = substring;
50 tokens += length;
51 }
52
53 if (end == FALSE && strstr (string + strlen (string) - length,
54 tokens - length) == NULL) return FALSE;
55
56 return TRUE;
57 }
58
59 static gamgi_bool static_pattern (char *string, char *pattern)
60 {
61 gamgi_bool start, end;
62 char *tokens = pattern;
63 int i, n_tokens;
64
65 /********************************************
66 * convert the whole pattern sequence to a *
67 * list of patterns separated by '\0' chars *
68 ********************************************/
69
70 n_tokens = 0;
71 for (i = 0; *pattern != '\0'; pattern++)
72 {
73 if (*pattern == '*')
74 {
75 if (*(pattern + 1) == '*') continue;
76 tokens[i++] = '\0';
77 n_tokens++;
78 }
79 else tokens[i++] = *pattern;
80 }
81 tokens[i] = '\0';
82
83 if (tokens[0] == '\0') start = TRUE;
84 else start = FALSE;
85
86 if (tokens[i - 1] == '\0') end = TRUE;
87 else end = FALSE;
88
89 if (start == TRUE && end == TRUE) n_tokens--;
90 if (start == FALSE && end == FALSE) n_tokens++;
91
92 return static_tokens (string, tokens, n_tokens, end);
93 }
94
95 static gamgi_bool static_line (int socket,
96 char *buffer, char *line, int *available)
97 {
98 static char *start;
99 char *end;
100 int vacant, copied;
101
102 /*******************
103 * initialize line *
104 *******************/
105
106 strcpy (line, "");
107 vacant = GAMGI_ENGINE_LINE - 1;
108
109 do
110 {
111 /********************************
112 * read from socket into buffer *
113 ********************************/
114
115 if (*available == 0)
116 {
117 *available = read (socket, buffer, GAMGI_IO_BUFFER);
118 if (*available <= 0) return FALSE;
119
120 start = buffer;
121 }
122
123 end = strchr (start, '\n');
124 if (end == NULL) end = start + *available - 1;
125
126 /********************
127 * \n is not copied *
128 ********************/
129
130 copied = end - start;
131 if (copied > vacant) return FALSE;
132 strncat (line, start, copied);
133 vacant -= copied;
134
135 /****************
136 * add 1 for \n *
137 ****************/
138
139 *available -= copied + 1;
140 start += copied + 1;
141 }
142 while (end == NULL);
143
144 return TRUE;
145 }
146
147 static char *static_read (int socket,
148 int code, char *buffer, char *line)
149 {
150 char more[5], end[5];
151 int available = 0;
152
153 sprintf (more, "%d-", code);
154 sprintf (end, "%d ", code);
155
156 do
157 {
158 if (static_line (socket, buffer, line, &available) == FALSE ||
159 strlen (line) < 4) return NULL;
160
161 line[4] = '\0';
162
163 if (strcmp (line, end) == 0) return line;
164
165 if (strcmp (line, more) != 0) return NULL;
166 }
167 while (1 > 0);
168 }
169
170 static gamgi_bool static_passive (unsigned char socket, char *line,
171 unsigned char *a1, unsigned char *a2, unsigned char *a3,
172 unsigned char *a4, unsigned char *p1, unsigned char *p2)
173 {
174 int n1, n2, n3, n4;
175
176 /**********************
177 * retrieve ip number *
178 **********************/
179
180 line = strpbrk (line+5, "0123456789");
181 if (sscanf (line, " %d, %d, %d, %d ", &n1, &n2, &n3, &n4) != 4)
182 return FALSE;
183
184 *a1 = n1; *a2 = n2; *a3 = n3; *a4 = n4;
185
186 /************************
187 * retrieve port number *
188 ************************/
189
190 line = strchr (line+1, ','); line = strchr (line+1, ',');
191 line = strchr (line+1, ','); line = strchr (line+1, ',');
192 if (sscanf (line+1, " %d, %d ", &n1, &n2) != 2)
193 return FALSE;
194
195 *p1 = n1; *p2 = n2;
196
197 return TRUE;
198 }
199
200 gamgi_bool gamgi_io_file_patterns (char *file, const char *filters)
201 {
202 char patterns[GAMGI_GTK_FILE_PATTERNS + 1];
203 char *pattern;
204
205 /******************************************
206 * divide sequence in individual patterns *
207 ******************************************/
208
209 strcpy (patterns, filters);
210 pattern = strtok (patterns, " ,");
211 do
212 {
213 if (static_pattern (file, pattern) == TRUE) return TRUE;
214 }
215 while ((pattern = strtok (NULL, " ,")) != NULL);
216
217 return FALSE;
218 }
219
220 char *gamgi_io_file_shortname (const char *fullname)
221 {
222 char *shortname;
223
224 shortname = strrchr (fullname, '/');
225 if (shortname != NULL) shortname++;
226 else shortname = (char *) fullname;
227
228 return shortname;
229 }
230
231 char *gamgi_io_file_extension (const char *fullname)
232 {
233 char *extension;
234
235 /**********************
236 * get file extension *
237 **********************/
238
239 extension = strrchr (fullname, '.');
240 if (extension != NULL)
241 {
242 extension++;
243
244 /*******************************
245 * make sure the dot is in the *
246 * file and not in a directory *
247 *******************************/
248
249 if (strchr (extension, '/') != NULL)
250 extension = NULL;
251 }
252
253 return extension;
254 }
255
256 /***************** external function *********************
257 * *
258 *********************************************************/
259
260 void gamgi_io_file_fprintf (FILE *fp, char *string, gamgi_bool *error)
261 {
262 /***************************************************************
263 * We set the error flag as FALSE before the first fprintf *
264 * call and check its state only after the last fprintf. If *
265 * error is now TRUE, then at least one fprintf call failed, *
266 * in which case we show an error message saying that we were *
267 * unable to successfully write the file and ask the user if *
268 * we should remove it (it is certainly corrupted, but reading *
269 * it might give the user a clue anyway about what went wrong) *
270 * *
271 * The upside of this procedure is that our code is much *
272 * simpler because we are not taking action immediately *
273 * if fprintf fails (at this stage the file is already open *
274 * in write mode, with sucess, so permission errors are not *
275 * likely to occur here, a typical error would occur here *
276 * for example if the hard disk filesystem fills up). We *
277 * can do this because we are not compromising Gamgi or the *
278 * system, just the file, which we remove (or not) in the end. *
279 * *
280 * The downside of this procedure is that our message in *
281 * the end cannot tell the user where the failure occurred. *
282 * This should not be a problem though, because as soon as *
283 * one fprintf fails, all the other should fail as well and *
284 * inspecting directly the file should clarify everything. *
285 ***************************************************************/
286
287 if (fprintf (fp, "%s", string) < 0) *error = TRUE;
288 }
289
290 char *gamgi_io_file_name (const char *fullname,
291 gamgi_window *window)
292 {
293 char *name, *shortname;
294
295 shortname = gamgi_io_file_shortname (fullname);
296
297 /************************************************
298 * make sure the shortname used for example *
299 * in error messages is not too long and always *
300 * fits inside the message string arrays. *
301 ************************************************/
302
303 if (gamgi_io_token_size_check (shortname, GAMGI_IO_SHORTNAME) == FALSE)
304 {
305 gamgi_io_error_open (shortname, window);
306 return NULL;
307 }
308
309 /***************************************
310 * make sure fullname is not too long, *
311 * so filename and hostname always fit *
312 * inside their string arrays *
313 **************************************/
314
315 if (gamgi_io_token_size_check (fullname, GAMGI_IO_FULLNAME) == FALSE)
316 {
317 gamgi_io_error_open (shortname, window);
318 return NULL;
319 }
320
321 /***************************************
322 * HTTP label must be in the beginning *
323 ***************************************/
324
325 name = strstr (fullname, "http://");
326 if (name != NULL && name != fullname)
327 {
328 gamgi_io_error_open (shortname, window);
329 return NULL;
330 }
331
332 /**************************************
333 * FTP label must be in the beginning *
334 **************************************/
335
336 name = strstr (fullname, "ftp://");
337 if (name != NULL && name != fullname)
338 {
339 gamgi_io_error_open (shortname, window);
340 return NULL;
341 }
342
343 return shortname;
344 }
345
346 gamgi_bool gamgi_io_file_http (const char *fullname, char *shortname,
347 gamgi_parser parser, gamgi_window *window, void *data)
348 {
349 int fd, size, number;
350 char buffer[GAMGI_IO_BUFFER];
351 char filename[GAMGI_ENGINE_LINE];
352 char hostname[GAMGI_ENGINE_LINE];
353 char *body;
354 gamgi_bool valid;
355
356 /*****************************
357 * get hostname and filename *
358 *****************************/
359
360 fullname += strlen("http://");
361
362 size = strcspn (fullname, "/");
363 strcpy (filename, fullname + size);
364
365 strncpy (hostname, fullname, size);
366 hostname[size] = '\0';
367
368 /*******************
369 * open connection *
370 *******************/
371
372 fd = gamgi_io_socket_name ("http", hostname);
373 if (fd < 0) return gamgi_io_error_open (shortname, window);
374
375 /*****************************************
376 * write instructions to the HTTP server *
377 *****************************************/
378
379 sprintf (buffer, "GET %s HTTP/1.1\r\n" "Host: %s\r\n"
380 "Pragma: no-cache\r\n" "Connection: close\r\n\r\n",
381 filename, hostname);
382 write (fd, buffer, strlen (buffer));
383
384 /**********************
385 * handle HTTP header *
386 **********************/
387
388 /***************************
389 * check header first line *
390 ***************************/
391
392 size = read (fd, buffer, GAMGI_IO_BUFFER);
393 if (size <= 0 || sscanf (buffer, "%*s %d %*s \n", &number) != 1
394 || number != GAMGI_IO_HTTP_OK)
395 {
396 close (fd);
397 return gamgi_io_error_open (shortname, window);
398 }
399
400 do
401 {
402 /*******************************
403 * ignore everything and just *
404 * search for header last line *
405 *******************************/
406
407 body = strstr (buffer, "\r\n\r\n");
408 if (body != NULL) break;
409
410 size = read (fd, buffer, GAMGI_IO_BUFFER);
411 if (size <= 0)
412 {
413 close (fd);
414 return gamgi_io_error_open (shortname, window);
415 }
416
417 } while (1 > 0);
418
419 if (body == NULL)
420 {
421 close (fd);
422 return gamgi_io_error_open (shortname, window);
423 }
424
425 /********************************************
426 * move forward the 4 char "\r\n\r\n" and *
427 * discount the header characters in buffer *
428 ********************************************/
429
430 body += 4;
431 size -= body - buffer;
432
433 /*******************
434 * parse HTTP file *
435 *******************/
436
437 valid = (parser) (fd, body, size, data);
438
439 close (fd);
440
441 return valid;
442 }
443
444 gamgi_bool gamgi_io_file_ftp (const char *fullname, char *shortname,
445 gamgi_parser parser, gamgi_window *window, void *data)
446 {
447 int fd_main, fd_data, size;
448 char buffer[GAMGI_IO_BUFFER], line[GAMGI_ENGINE_LINE];
449 char filename[GAMGI_ENGINE_LINE], hostname[GAMGI_ENGINE_LINE];
450 char *last;
451 unsigned char a1, a2, a3, a4, p1, p2;
452 gamgi_bool valid;
453
454 /*****************************
455 * get hostname and filename *
456 *****************************/
457
458 fullname += strlen("ftp://");
459
460 size = strcspn (fullname, "/");
461 strcpy (filename, fullname + size);
462
463 strncpy (hostname, fullname, size);
464 hostname[size] = '\0';
465
466 /********************
467 * open main socket *
468 ********************/
469
470 if ((fd_main = gamgi_io_socket_name ("ftp", hostname)) < 0)
471 return gamgi_io_error_open (shortname, window);
472
473 if (static_read (fd_main, GAMGI_IO_FTP_GREETINGS, buffer, line) == NULL)
474 {
475 close (fd_main);
476 return gamgi_io_error_open (shortname, window);
477 }
478
479 /******************
480 * enter username *
481 ******************/
482
483 sprintf (buffer, "USER anonymous\r\n");
484 if (write (fd_main, (char *) buffer, strlen (buffer)) < 0)
485 {
486 close (fd_main);
487 return gamgi_io_error_open (shortname, window);
488 }
489
490 if (static_read (fd_main, GAMGI_IO_FTP_USER, buffer, line) == NULL)
491 {
492 close (fd_main);
493 return gamgi_io_error_open (shortname, window);
494 }
495
496 /******************
497 * enter password *
498 ******************/
499
500 sprintf (buffer, "PASS gamgi@www.gamgi.org\r\n");
501 if (write (fd_main, (char *) buffer, strlen (buffer)) < 0)
502 {
503 close (fd_main);
504 return gamgi_io_error_open (shortname, window);
505 }
506
507 if (static_read (fd_main, GAMGI_IO_FTP_PASSWORD, buffer, line) == NULL)
508 {
509 close (fd_main);
510 return gamgi_io_error_open (shortname, window);
511 }
512
513 /**********************************
514 * set data type (text or binary) *
515 **********************************/
516
517 sprintf (buffer, "TYPE A\r\n");
518 if (write (fd_main, (char *) buffer, strlen (buffer)) < 0)
519 {
520 close (fd_main);
521 return gamgi_io_error_open (shortname, window);
522 }
523
524 if (static_read (fd_main, GAMGI_IO_FTP_TYPE, buffer, line) == NULL)
525 {
526 close (fd_main);
527 return gamgi_io_error_open (shortname, window);
528 }
529
530 /************************************
531 * enter passive mode: get IP, Port *
532 ************************************/
533
534 sprintf (buffer, "PASV\r\n");
535 if (write (fd_main, (char *) buffer, strlen (buffer)) < 0)
536 {
537 close (fd_main);
538 return gamgi_io_error_open (shortname, window);
539 }
540
541 if ((last = static_read (fd_main, GAMGI_IO_FTP_PASSIVE, buffer, line)) == NULL)
542 {
543 close (fd_main);
544 return gamgi_io_error_open (shortname, window);
545 }
546
547 if (static_passive (fd_main, last, &a1, &a2, &a3, &a4, &p1, &p2) == FALSE)
548 {
549 close (fd_main);
550 return gamgi_io_error_open (shortname, window);
551 }
552
553 /********************
554 * open data socket *
555 ********************/
556
557 if ((fd_data = gamgi_io_socket_number ("ftp", a1, a2, a3, a4, p1, p2)) < 0)
558 {
559 close (fd_main);
560 return gamgi_io_error_open (shortname, window);
561 }
562
563 /****************
564 * ask for file *
565 ****************/
566
567 sprintf (buffer, "RETR %s\r\n", filename);
568 if (write (fd_main, (char *) buffer, strlen (buffer)) < 0)
569 {
570 close (fd_main);
571 close (fd_data);
572 return gamgi_io_error_open (shortname, window);
573 }
574
575 if (static_read (fd_main, GAMGI_IO_FTP_FILE, buffer, line) == NULL)
576 {
577 close (fd_main);
578 close (fd_data);
579 return gamgi_io_error_open (shortname, window);
580 }
581
582 /************************************
583 * parse FTP file using data socket *
584 ************************************/
585
586 valid = (parser) (fd_data, NULL, 0, data);
587
588 close (fd_data);
589
590 if (static_read (fd_main, GAMGI_IO_FTP_READ, buffer, line) == NULL)
591 {
592 close (fd_main);
593 return gamgi_io_error_open (shortname, window);
594 }
595
596 close (fd_main);
597
598 return valid;
599 }
600
601 gamgi_bool gamgi_io_file_local (const char *fullname, char *shortname,
602 gamgi_parser parser, gamgi_window *window, void *data)
603 {
604 int fd;
605 gamgi_bool valid;
606
607 /*************
608 * open file *
609 *************/
610
611 fd = open (fullname, O_RDONLY);
612 if (fd < 0) return gamgi_io_error_open (shortname, window);
613
614 /**************
615 * parse file *
616 **************/
617
618 valid = (parser) (fd, NULL, 0, data);
619
620 /**************
621 * close file *
622 **************/
623
624 close (fd);
625
626 return valid;
627 }
628
629 gamgi_bool gamgi_io_file_protocol (const char *fullname, char *filename,
630 gamgi_parser parser, gamgi_window *window, void *data)
631 {
632 if (strstr (fullname, "http://") != NULL)
633 return gamgi_io_file_http (fullname, filename, parser, window, data);
634 else if (strstr (fullname, "ftp://") != NULL)
635 return gamgi_io_file_ftp (fullname, filename, parser, window, data);
636 else
637 return gamgi_io_file_local (fullname, filename, parser, window, data);
638 }
639
640 gamgi_bool gamgi_io_file_export_ps (FILE *fp,
641 int width, int height, gamgi_bool *error)
642 {
643 int components, i;
644 unsigned char *pixels;
645 char string[GAMGI_ENGINE_LINE];
646
647 /*************
648 * grab data *
649 *************/
650
651 components = 3;
652 pixels = gamgi_mesa_area_read (0, 0, width, height);
653
654 /***********************************************************
655 * Write header, adapted from: 1) the header produced *
656 * by Gimp 2.4.6 when exporting .eps encapsulated *
657 * postcript files (without level 2), written by Peter *
658 * Kirchgessner; 2) the book Postcript Language, Tutorial *
659 * and Cookbook, Adobe Systems Inc., Addison-Wesley, 1986 *
660 ***********************************************************/
661
662 gamgi_io_file_fprintf (fp, "%!PS-Adobe-3.0 EPSF-3.0\n", error);
663 sprintf (string, "%%%%Creator: GAMGI %s\n", GAMGI_IO_VERSION);
664 gamgi_io_file_fprintf (fp, string, error);
665 gamgi_io_file_fprintf (fp, "%%DocumentData: Clean7Bit\n", error);
666 gamgi_io_file_fprintf (fp, "%%LanguageLevel: 2\n", error);
667 gamgi_io_file_fprintf (fp, "%%Pages: 1\n", error);
668 sprintf (string, "%%%%BoundingBox: 0 0 %d %d\n", width, height);
669 gamgi_io_file_fprintf (fp, string, error);
670 gamgi_io_file_fprintf (fp, "%%EndComments\n", error);
671 sprintf (string, "/scanline %d string def\n", width * components);
672 gamgi_io_file_fprintf (fp, string, error);
673 sprintf (string, "%d %d scale\n", width, height);
674 gamgi_io_file_fprintf (fp, string, error);
675 sprintf (string, "%d %d %d\n", width, height, 8);
676 gamgi_io_file_fprintf (fp, string, error);
677 sprintf (string, "[%d 0 0 %d 0 0]\n", width, height);
678 gamgi_io_file_fprintf (fp, string, error);
679 gamgi_io_file_fprintf (fp, "{currentfile scanline readhexstring pop}\n", error);
680 sprintf (string, "false %d\n", components);
681 gamgi_io_file_fprintf (fp, string, error);
682 gamgi_io_file_fprintf (fp, "colorimage\n", error);
683
684 /********************************************
685 * Write data: adapted from the book OpenGL *
686 * Programming for the X Window System p98, *
687 * Mark J. Kilgard, Addison-Wesley, 1996. *
688 ********************************************/
689
690 i = 0;
691 while (i < width * height * components)
692 {
693 sprintf (string, "%02x", pixels[i++]);
694 gamgi_io_file_fprintf (fp, string, error);
695 if (i % 40 == 0) gamgi_io_file_fprintf (fp, "\n", error);
696 }
697 if (i % 40 != 0) gamgi_io_file_fprintf (fp, "\n", error);
698
699 /*******************************************
700 * show postscript page and free resources *
701 *******************************************/
702
703 gamgi_io_file_fprintf (fp, "showpage\n", error);
704 free (pixels);
705
706 return TRUE;
707 }
708
709 gamgi_bool gamgi_io_file_export_ppm (FILE *fp,
710 int width, int height, gamgi_bool *error)
711 {
712 unsigned char *pixels;
713 char string[GAMGI_ENGINE_LINE];
714 int i, components, maximum, offset;
715
716 /***************************************************************
717 * grab data: assume a maximum depth of 8 bits per rgb channel *
718 * so each color component can take values between 0 and 255 *
719 ***************************************************************/
720
721 components = 3;
722 pixels = gamgi_mesa_area_read (0, 0, width, height);
723 maximum = GAMGI_IO_PPM_MAX;
724
725 /****************
726 * write header *
727 ****************/
728
729 gamgi_io_file_fprintf (fp, "P3\n", error);
730
731 sprintf (string, "#Made with GAMGI %s\n", GAMGI_IO_VERSION);
732 gamgi_io_file_fprintf (fp, string, error);
733
734 sprintf (string, "%d %d\n%d\n", width, height, maximum);
735 gamgi_io_file_fprintf (fp, string, error);
736
737 /**********************************************
738 * write data: from end to start, because ppm *
739 * formats read data from top to bottom while *
740 * OpenGL array grabs data from bottom to top *
741 **********************************************/
742
743 while (height-- > 0)
744 {
745 offset = components * width * height;
746 for (i = 0; i < width; i++)
747 {
748 sprintf (string, "%d %d %d ",
749 pixels[offset + 0], pixels[offset + 1], pixels[offset + 2]);
750 gamgi_io_file_fprintf (fp, string, error);
751 offset += components;
752 }
753 gamgi_io_file_fprintf (fp, "\n", error);
754 }
755
756 /******************
757 * free resources *
758 ******************/
759
760 free (pixels);
761
762 return TRUE;
763 }
764
765 gamgi_bool gamgi_io_file_export_png (char *fullname,
766 FILE *fp, int width, int height, gamgi_bool *error)
767 {
768 char auxname[2 * GAMGI_ENGINE_TOKEN];
769 char command[2 * GAMGI_ENGINE_LINE];
770
771 /**********************************
772 * 1) create fullname ppm file *
773 * 2) convert to auxname png file *
774 * (with special name, to avoid *
775 * destroying a user's file!) *
776 * 3) move auxname to fullname *
777 **********************************/
778
779 gamgi_io_file_export_ppm (fp, width, height, error);
780 if (*error != 0) return FALSE;
781
782 sprintf (auxname, "gamgi%d", getpid ());
783
784 sprintf (command, "(%s %s >%s; mv -f %s %s) &",
785 GAMGI_IO_PNMTOPNG, fullname, auxname, auxname, fullname);
786 system (command);
787
788 return TRUE;
789 }
790
791 gamgi_bool gamgi_io_file_export_jpeg (char *fullname,
792 FILE *fp, int width, int height, gamgi_bool *error)
793 {
794 char auxname[2 * GAMGI_ENGINE_TOKEN];
795 char command[2 * GAMGI_ENGINE_LINE];
796
797 /**********************************
798 * 1) create fullname ppm file *
799 * 2) convert to auxname png file *
800 * (with special name, to avoid *
801 * destroying a user's file!) *
802 * 3) move auxname to fullname *
803 **********************************/
804
805 gamgi_io_file_export_ppm (fp, width, height, error);
806 if (*error != 0) return FALSE;
807
808 sprintf (auxname, "gamgi%d", getpid ());
809
810 sprintf (command, "(%s %s >%s; mv -f %s %s) &",
811 GAMGI_IO_PNMTOJPEG, fullname, auxname, auxname, fullname);
812 system (command);
813
814 return TRUE;
815 }
816
817 gamgi_bool gamgi_io_file_export_tiff (char *fullname,
818 FILE *fp, int width, int height, gamgi_bool *error)
819 {
820 char auxname[2 * GAMGI_ENGINE_TOKEN];
821 char command[2 * GAMGI_ENGINE_LINE];
822
823 /**********************************
824 * 1) create fullname ppm file *
825 * 2) convert to auxname png file *
826 * (with special name, to avoid *
827 * destroying a user's file!) *
828 * 3) move auxname to fullname *
829 **********************************/
830
831 gamgi_io_file_export_ppm (fp, width, height, error);
832 if (*error != 0) return FALSE;
833
834 sprintf (auxname, "gamgi%d", getpid ());
835
836 sprintf (command, "(%s -color %s >%s; mv -f %s %s) &",
837 GAMGI_IO_PNMTOTIFF, fullname, auxname, auxname, fullname);
838 system (command);
839
840 return TRUE;
841 }
842
843 gamgi_bool gamgi_io_file_read (char *fullname, gamgi_window *window)
844 {
845 char *extension;
846
847 /**********************
848 * get file extension *
849 **********************/
850
851 extension = gamgi_io_file_extension (fullname);
852
853 /*******************************
854 * read according to extension *
855 *******************************/
856
857 if (extension == NULL)
858 return gamgi_expat_import_gml (fullname, window);
859 if (strcmp (extension, "xyz") == 0)
860 return gamgi_io_xyz_import (fullname, window);
861 return gamgi_expat_import_gml (fullname, window);
862 }
863
864 gamgi_bool gamgi_io_file_shell (int argc,
865 char **argv, gamgi_window *window)
866 {
867 int i;
868
869 /***************************
870 * load command line files *
871 * *
872 * if an error is found: *
873 * 1) ignore wrong file; *
874 * 2) show error message; *
875 * 3) ignore next files; *
876 ***************************/
877
878 for (i = 1; i < argc; i++)
879 {
880 if (gamgi_io_file_read (argv[i], window) == FALSE) return FALSE;
881 }
882
883 return TRUE;
884 }
885
886 gamgi_bool gamgi_io_file_write (char *fullname, gamgi_window *window)
887 {
888 gamgi_bool error = FALSE;
889 GtkAllocation allocation;
890 FILE *fp;
891 char *shortname;
892 char *extension;
893 int width, height;
894
895 /************************************************
896 * discard the pathname, keep only the filename *
897 ************************************************/
898
899 shortname = gamgi_io_file_shortname (fullname);
900
901 /*******************************
902 * open file in overwrite mode *
903 *******************************/
904
905 fp = fopen (fullname, "w");
906 if (fp == NULL)
907 {
908 gamgi_io_error_write (shortname, window);
909 return FALSE;
910 }
911
912 /**********************
913 * get file extension *
914 **********************/
915
916 extension = gamgi_io_file_extension (fullname);
917
918 /*******************************************************
919 * write according to extension: when the extension is *
920 * nonexistent or unrecognized export a GAMGI xml file *
921 *******************************************************/
922
923 gtk_widget_get_allocation (window->area, &allocation);
924 width = allocation.width;
925 height = allocation.height;
926
927 if (extension == NULL)
928 gamgi_expat_export_gml (fp, window, &error);
929 else if (strcmp (extension, "jpeg") == 0 || strcmp (extension, "jpg") == 0)
930 gamgi_io_file_export_jpeg (fullname, fp, width, height, &error);
931 else if (strcmp (extension, "png") == 0)
932 gamgi_io_file_export_png (fullname, fp, width, height, &error);
933 else if (strcmp (extension, "eps") == 0 || strcmp (extension, "ps") == 0)
934 gamgi_io_file_export_ps (fp, width, height, &error);
935 else if (strcmp (extension, "ppm") == 0)
936 gamgi_io_file_export_ppm (fp, width, height, &error);
937 else if (strcmp (extension, "tiff") == 0 || strcmp (extension, "tif") == 0)
938 gamgi_io_file_export_tiff (fullname, fp, width, height, &error);
939 else if (strcmp (extension, "x3d") == 0)
940 gamgi_expat_export_x3d (fp, window, &error);
941 else if (strcmp (extension, "xyz") == 0)
942 gamgi_io_xyz_export (fp, window, &error);
943 else
944 gamgi_expat_export_gml (fp, window, &error);
945
946 /**************
947 * close file *
948 **************/
949
950 fclose (fp);
951
952 /******************************************
953 * in the end, check if an error occurred *
954 * during writing to file (disk full?) *
955 ******************************************/
956
957 if (error == TRUE)
958 {
959 gamgi_io_error_write (shortname, window);
960 return FALSE;
961 }
962
963 return TRUE;
964 }
965
966 void gamgi_io_file_overwrite (char *filename,
967 gamgi_callback2 function, gamgi_window *window)
968 {
969 char string[GAMGI_ENGINE_LINE];
970 char *shortname;
971 FILE *fp;
972
973 /************************************************
974 * discard the pathname, keep only the filename *
975 ************************************************/
976
977 shortname = gamgi_io_file_shortname (filename);
978
979 /*****************************
980 * open file in append mode, *
981 * to check file existence *
982 *****************************/
983
984 fp = fopen (filename, "a+");
985 if (fp == NULL)
986 { gamgi_io_error_write (shortname, window);
987 return; }
988
989 /*******************
990 * overwrite file? *
991 *******************/
992
993 fseek(fp, 0, SEEK_SET);
994 fgetc(fp);
995 if (feof(fp) == 0)
996 { fclose (fp);
997 sprintf (string, "Overwrite file \"%s\"?", shortname);
998 gamgi_gtk_dialog_question_create ("Warning", string, function, window);
999 return; }
1000
1001 /*****************************
1002 * close file in append mode *
1003 *****************************/
1004
1005 fclose (fp);
1006 (*function) (NULL, window);
1007 }