Patch provided by Shaul Kedem: Compressed files are back!
authorTon Roosendaal <ton@blender.org>
Wed, 27 Jul 2005 19:46:06 +0000 (19:46 +0000)
committerTon Roosendaal <ton@blender.org>
Wed, 27 Jul 2005 19:46:06 +0000 (19:46 +0000)
He even made a nice doc in wiki:
http://wiki.blender.org/bin/view.pl/Blenderdev/Blendgz

Usage: set the option "Compress File" in the main "File" pulldown menu.
This setting is a user-def, meaning it is not changed on reading files.
If you want it default, save it with CTRL+U.

The longest debate went over the file naming convention. Shaul started
with .blend.gz files, which gave issues in Blender because of the code
hanging out everywhere that detects blender files, and that appends the
.blend extension if needed.

Daniel Dunbar proposed to just save it as .blend, and not bother users
with such details. This is indeed the most elegant solution, with as
only drawback that old Blender executables cannot read it.
This drawback isn't very relevant at the moment, since we're heading
towards a release that isn't upward compatible anyway... the recode
going on on Meshes, Modfiers, Armatures, Poses, Actions, NLA already
have upward compatibility issues.
We might check - during the next month(s) - on a builtin system to
warn users in the future when we change things that make a file risky
to read in an older release.

15 files changed:
source/blender/blenkernel/intern/action.c
source/blender/blenkernel/intern/deform.c
source/blender/blenkernel/intern/exotic.c
source/blender/blenlib/BLI_blenlib.h
source/blender/blenlib/intern/fileops.c
source/blender/blenlib/intern/util.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/readfile.h
source/blender/blenloader/intern/writefile.c
source/blender/makesdna/DNA_userdef_types.h
source/blender/src/buttons_editing.c
source/blender/src/filesel.c
source/blender/src/header_filesel.c
source/blender/src/header_info.c
source/blender/src/usiblender.c

index ed8749eb440a5f6f8ad185dcedfd603f2a899d1d..f465f85b98d26b26f7edbf42668518f45e382dd4 100644 (file)
@@ -52,6 +52,7 @@
 #include "BKE_armature.h"
 #include "BKE_blender.h"
 #include "BKE_constraint.h"
+#include "BKE_displist.h"
 #include "BKE_global.h"
 #include "BKE_ipo.h"
 #include "BKE_library.h"
index c99b3986059ea8a10022a3c174615fd4d07c583b..8e33303d137e266b9b8faf34a0f5d52d7c448303 100644 (file)
@@ -230,7 +230,6 @@ void hook_object_deform(Object *ob, int index, float *vec)
 
 void mesh_modifier(Object *ob, float (**vertexCos_r)[3])
 {
-       MVert *origMVert=NULL;
        Mesh *me= ob->data;
        float (*vertexCos)[3] = NULL;
        int a;
index 7f0aee186640dcbb328ce02fe46a330e46e32d54..0de307a98fb053de215700ce2402836cf4153920 100644 (file)
 
 #include "blendef.h"
 
+#include "zlib.h"
+
 static int is_dxf(char *str);
 static void dxf_read(char *filename);
 static int is_stl(char *str);
@@ -2376,7 +2378,8 @@ static void displist_to_objects(ListBase *lbase)
 int BKE_read_exotic(char *name)
 {
        ListBase lbase={0, 0};
-       int file, len;
+       int len;
+       gzFile gzfile;
        char str[32];
        int *s0 = (int*) str;
        int retval = 0;
@@ -2385,15 +2388,15 @@ int BKE_read_exotic(char *name)
 
        len= strlen(name);
        if (name[len-1] !='/' && name[len-1] != '\\') {
-               file = open(name, O_BINARY|O_RDONLY);
+               gzfile = gzopen(name,"rb");
 
-               if (file <= 0) {
+               if (NULL == gzfile ) {
                        error("Can't open file: %s", name);
                } else {
-                       read(file, str, 31);
-                       close(file);
+                       gzread(gzfile, str, 31);
+                       gzclose(gzfile);
 
-                       if ((*s0 != FORM) && (strncmp(str, "BLEN", 4) != 0)) {
+                       if ((*s0 != FORM) && (strncmp(str, "BLEN", 4) != 0) && !BLI_testextensie(name,".blend.gz")) {
 
                                waitcursor(1);
                                
index 167050d160a78a64890548f098e7e9cb205db275..2c11250c9443e258b228fa83c6a1afa51a93efa3 100644 (file)
@@ -256,6 +256,7 @@ int BLI_backup(char *file, char *from, char *to);
 int   BLI_exists(char *file);
 int   BLI_copy_fileops(char *file, char *to);
 int   BLI_rename(char *from, char *to);
+int   BLI_gzip(char *from, char *to);
 int   BLI_delete(char *file, int dir, int recursive);
 int   BLI_move(char *file, char *to);
 int   BLI_touch(char *file);
index 69e8790c8942a81c028e56321489102f93b47e28..6442a304983e4f9050684102e45c0da92ec96b3a 100644 (file)
 #include "BLI_fileops.h"
 #include "BLI_callbacks.h"
 
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "BKE_utildefines.h"
+#include "zlib.h"
+#include <errno.h>
+
 /* implementations: */
 char *first_slash(char *string) {
        char *ffslash, *fbslash;
@@ -82,6 +90,37 @@ char *BLI_last_slash(char *string) {
        else return lfslash;
 }
 
+/* gzip the file in from and write it to "to". 
+ return -1 if zlib fails, -2 if the originating file does not exist
+ note: will remove the "from" file
+  */
+int BLI_gzip(char *from, char *to) {
+       char buffer[10240];
+       int file;
+       int readsize = 0;
+       
+       gzFile gzfile = gzopen(to,"wb"); 
+       if (NULL == gzfile) return -1;
+       
+       file = open(from,O_BINARY|O_RDONLY);
+       
+       if ( -1 == file )       return -2;
+
+       while ( 1 )
+       {
+               readsize = read(file, buffer, 10240);
+               
+               if (readsize <= 0) break;
+               
+               gzwrite(gzfile,buffer,readsize);
+       }
+       
+       gzclose(gzfile);
+       close(file);
+       
+       remove(from);
+}
+
 #ifdef WIN32
 
 static char str[MAXPATHLEN+12];
index 2cd0bce93b9ce1433a0ffcd78ab07e927bde0ed9..2095b537d79698c1b5bf16bc82e741efe3c6fb65 100644 (file)
@@ -121,6 +121,11 @@ int BLI_stringdec(char *string, char *kop, char *staart, unsigned short *numlen)
                else if (BLI_strncasecmp(string + len - 6, ".trace", 6) == 0) len -= 6;
        }
        
+       if (len > 9) {
+               if (BLI_strncasecmp(string + len - 9, ".blend.gz", 9) == 0) len -= 9;
+       }
+               
+       
        if (len == len2) {
                if (len > 4) {
                        /* handle .jf0 en .jf1 for jstreams */
index cb37ac1ff0177d81eacf70c75b3acb686eea0faa..b916914fd50d5ad1bd494005ae505ac2cbd1dd7c 100644 (file)
 #include "mydevice.h"
 #include "blendef.h"
 
+#include "zlib.h"
+
+#include <errno.h>
+
 /*
  Remark: still a weak point is the newadress() function, that doesnt solve reading from
  multiple files at the same time
@@ -774,6 +778,19 @@ static int fd_read_from_file(FileData *filedata, void *buffer, int size)
        return (readsize);
 }
 
+static int fd_read_gzip_from_file(FileData *filedata, void *buffer, int size)
+{
+       int readsize = gzread(filedata->gzfiledes, buffer, size);
+
+       if (readsize < 0) {
+               readsize = EOF;
+       } else {
+               filedata->seek += readsize;
+       }
+
+       return (readsize);
+}
+
 static int fd_read_from_memory(FileData *filedata, void *buffer, int size)
 {
                // don't read more bytes then there are available in the buffer
@@ -840,6 +857,7 @@ static FileData *filedata_new(void)
        FileData *fd = MEM_callocN(sizeof(FileData), "FileData");
 
        fd->filedes = -1;
+       fd->gzfiledes = NULL;
 
                /* XXX, this doesn't need to be done all the time,
                 * but it keeps us reentrant,  remove once we have
@@ -875,7 +893,7 @@ static FileData *blo_decode_and_check(FileData *fd, BlendReadError *error_r)
 
 FileData *blo_openblenderfile(char *name, BlendReadError *error_r)
 {
-       int file;
+       gzFile gzfile;
        char name1[FILE_MAXDIR+FILE_MAXFILE];
        
        /* library files can have stringcodes */
@@ -885,17 +903,16 @@ FileData *blo_openblenderfile(char *name, BlendReadError *error_r)
        else
                strcpy(G.sce, name);    // global... is set in blender.c setup_app_data too. should be part of Main immediate?
        
-       file= open(name1, O_BINARY|O_RDONLY);
+       gzfile= gzopen(name1, "rb");
 
-       if (file == -1) {
+       if (NULL == gzfile) {
                *error_r = BRE_UNABLE_TO_OPEN;
                return NULL;
        } else {
                FileData *fd = filedata_new();
-               fd->filedes = file;
+               fd->gzfiledes = gzfile;
                BLI_strncpy(fd->filename, name, sizeof(fd->filename));  // now only in use by library append
-               fd->buffersize = BLI_filesize(file);
-               fd->read = fd_read_from_file;
+               fd->read = fd_read_gzip_from_file;
 
                return blo_decode_and_check(fd, error_r);
        }
@@ -937,10 +954,16 @@ FileData *blo_openblendermemfile(MemFile *memfile, BlendReadError *error_r)
 void blo_freefiledata(FileData *fd)
 {
        if (fd) {
+               
                if (fd->filedes != -1) {
                        close(fd->filedes);
                }
 
+               if (fd->gzfiledes != NULL)
+               {
+                       gzclose(fd->gzfiledes);
+               }
+
                if (fd->buffer && !(fd->flags & FD_FLAGS_NOT_MY_BUFFER)) {
                        MEM_freeN(fd->buffer);
                        fd->buffer = 0;
@@ -971,7 +994,7 @@ void blo_freefiledata(FileData *fd)
 
 int BLO_has_bfile_extension(char *str)
 {
-       return (BLI_testextensie(str, ".ble") || BLI_testextensie(str, ".blend"));
+       return (BLI_testextensie(str, ".ble") || BLI_testextensie(str, ".blend")||BLI_testextensie(str, ".blend.gz"));
 }
 
 /* ************** OLD POINTERS ******************* */
index 6389cfaa6f5d58943107fdbdafa9c590cfaeb693..efdfa9f76bf9dd4953b5207f4b9a097995c63269 100644 (file)
@@ -33,6 +33,8 @@
 #ifndef READFILE_H
 #define READFILE_H
 
+#include "zlib.h"
+
 struct OldNewMap;
 struct MemFile;
 
@@ -52,6 +54,8 @@ typedef struct FileData {
 
        // variables needed for reading from file
        int filedes;
+       gzFile gzfiledes;
+
        // now only in use for library appending
        char filename[FILE_MAXDIR+FILE_MAXFILE];
        
index 61c7911ffcab1a5ea386aa3e9a1a305eb0d0e2c7..3ae58e92b036d4cb1352d2d0650cea8f2c898dfd 100644 (file)
@@ -167,6 +167,9 @@ Important to know is that 'streaming' has been added to files, for Blender Publi
 #include "readfile.h"
 #include "genfile.h"
 
+#include "zlib.h"
+
+#include <errno.h>
 
 /* ********* my write, buffered writing with minimum 50k chunks ************ */
 
@@ -1607,10 +1610,28 @@ int BLO_write_file(char *dir, int write_flags, char **error_r)
        close(file);
 
        if(!fout) {
+               if(write_flags & G_FILE_COMPRESS)
+               {       
+                       // compressed files have the same ending as regular files... only from 2.4!!!
+                       
+                       int ret = BLI_gzip(tempname, dir);
+                       
+                       if(-1==ret) {
+                               *error_r= "Failed opening .gz file";
+                               return 0;
+                       }
+                       if(-2==ret) {
+                               *error_r= "Failed opening .blend file for compression";
+                               return 0;
+                       }
+               }
+               else
                if(BLI_rename(tempname, dir) < 0) {
                        *error_r= "Can't change old file. File saved with @";
                        return 0;
                }
+
+               
        } else {
                remove(tempname);
 
index 9f2e069173c142329a90d16211bb87845005452a..7d00460403a0ebe5ae0acd08763923b3ded941e2 100644 (file)
@@ -180,6 +180,7 @@ extern UserDef U; /* from usiblender.c !!!! */
 #define USER_TWOBUTTONMOUSE            4096
 #define USER_NONUMPAD                  8192
 #define USER_LMOUSESELECT              16384
+#define USER_FILECOMPRESS              32768
 
 /* viewzom */
 #define USER_ZOOM_CONT                 0
index f92a9666b53592926b85f40bbf607893d75b82bf..d22071e0e111382b20cab5a436b780f4572d09b1 100644 (file)
 
 #include "butspace.h" // own module
 
-static int decim_faces=0;
 static short degr= 90, step= 9, turn= 1;
 static float extr_offs= 1.0;
 static float editbutweight=1.0;
index 20daef3a9a922225a8bcc61f4b6a71a715db7572..2cc264edfa14c2af1b2ed42d75079fb5dfb6a013 100644 (file)
@@ -704,6 +704,7 @@ static void split_sfile(SpaceFile *sfile, char *s1)
                else test_flags_file(sfile);
        }
        strcpy(sfile->file, file);
+               
        BLI_make_file_string(G.sce, sfile->dir, dir, "");
 }
 
@@ -917,6 +918,7 @@ static void print_line(SpaceFile *sfile, struct direntry *files, int x, int y)
                linerect(boxcol, x, y);
        }
 
+       // this is where the little boxes in the file view are being drawn according to the file type
        if(files->flags & BLENDERFILE) {
                cpack(0xA0A0);
                glRects(x-14,  y,  x-8,  y+7);
@@ -1149,8 +1151,9 @@ void drawfilespace(ScrArea *sa, void *spacedata)
        }
        else loadbutton= 0;
 
-       uiDefBut(block, TEX,        1,"",       textrct.xmin, filebuty1, textrct.xmax-textrct.xmin-loadbutton, 21, sfile->file, 0.0, (float)FILE_MAXFILE-1, 0, 0, "");
-       uiDefBut(block, TEX,        2,"",       textrct.xmin, filebuty2, textrct.xmax-textrct.xmin-loadbutton, 21, sfile->dir, 0.0, (float)FILE_MAXFILE-1, 0, 0, "");
+       uiDefBut(block, TEX,1,"",       textrct.xmin, filebuty1, textrct.xmax-textrct.xmin-loadbutton, 21, sfile->file, 0.0, (float)FILE_MAXFILE-1, 0, 0, "");
+       uiDefBut(block, TEX,2,"",       textrct.xmin, filebuty2, textrct.xmax-textrct.xmin-loadbutton, 21, sfile->dir, 0.0, (float)FILE_MAXFILE-1, 0, 0, "");
+
        if(loadbutton) {
                uiSetCurFont(block, UI_HELV);
                uiDefBut(block, BUT,        5, sfile->title,    textrct.xmax-loadbutton, filebuty2, loadbutton, 21, sfile->dir, 0.0, (float)FILE_MAXFILE-1, 0, 0, "");
index 654b73eb20d39442d8bade0652c3b0344999f20a..954b47cc5a72d6504bc65a4c2b7f262d249aa5c3 100644 (file)
@@ -146,7 +146,10 @@ void file_buttons(void)
                uiBlockEndAlign(block);
        } else if(sfile->type==FILE_BLENDER) {
                uiDefButI(block, TOGN|BIT|10, B_REDR, "Load UI", xco+=XIC,0,80,YIC, &G.fileflags, 0, 0, 0, 0, "Load the UI setup as well as the scene data");
+               
+       
                xco+=100;
+
        }
 
        if(sfile->type==FILE_UNIX) {
index ebb3843a3463fbc0060640ee677e686c31f94b3e..69e05fefdcc05d31a0456900370d6da7057e4faa 100644 (file)
@@ -572,95 +572,6 @@ static void write_runtime_check(char *str)
 /************************** MAIN MENU *****************************/
 /************************** FILE *****************************/
 
-#if 0
-static void do_info_file_optionsmenu(void *arg, int event)
-{
-       G.fileflags ^= (1 << event);
-
-       // allqueue(REDRAWINFO, 0);
-}
-#endif
-
-#if GAMEBLENDER == 1
-
-#if 0
-static uiBlock *info_file_optionsmenu(void *arg_unused)
-{
-       uiBlock *block;
-       short yco= 0, xco = 20;
-
-       block= uiNewBlock(&curarea->uiblocks, "runtime_options", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
-       uiBlockSetButmFunc(block, do_info_file_optionsmenu, NULL);
-       uiBlockSetXOfs(block,-40);      // offset to parent button
-       
-       /* flags are case-values */
-       uiDefBut(block, BUTM, 1, "Compress File",       xco, yco-=20, 100, 19, NULL, 0.0, 0.0, 0, G_FILE_COMPRESS_BIT, "Enables file compression");
-/*
-       uiDefBut(block, BUTM, 1, "Sign File",   xco, yco-=20, 100, 19, NULL, 0.0, 0.0, 0, G_FILE_SIGN_BIT, "Add signature to file");
-       uiDefBut(block, BUTM, 1, "Lock File",   xco, yco-=20, 100, 19, NULL, 0.0, 0.0, 0, G_FILE_LOCK_BIT, "Protect the file from editing by others");
-*/
-       uiTextBoundsBlock(block, 50);
-
-       /* Toggle buttons */
-       
-       yco= 0;
-       xco -= 20;
-       uiBlockSetEmboss(block, UI_EMBOSSM);
-       uiBlockSetButmFunc(block, NULL, NULL);
-       /* flags are defines */
-       uiDefIconButI(block, ICONTOG|BIT|G_FILE_COMPRESS_BIT, 0, ICON_CHECKBOX_DEHLT, xco, yco-=20, 19, 19, &G.fileflags, 0.0, 0.0, 0, 0, "");
-/*
-       uiDefIconButI(block, ICONTOG|BIT|G_FILE_SIGN_BIT, 0, ICON_CHECKBOX_DEHLT, xco, yco-=20, 19, 19, &G.fileflags, 0.0, 0.0, 0, 0, "");
-       uiDefIconButI(block, ICONTOG|BIT|G_FILE_LOCK_BIT, 0, ICON_CHECKBOX_DEHLT, xco, yco-=20, 19, 19, &G.fileflags, 0.0, 0.0, 0, 0, "");
-*/
-       uiBlockSetDirection(block, UI_RIGHT);
-               
-       return block;
-}
-
-static uiBlock *info_runtime_optionsmenu(void *arg_unused)
-{
-       uiBlock *block;
-       short yco= 0, xco = 20;
-
-       block= uiNewBlock(&curarea->uiblocks, "add_surfacemenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
-       uiBlockSetXOfs(block, -40);  // offset to parent button
-       uiBlockSetEmboss(block, UI_EMBOSSM);
-
-       uiDefBut(block, LABEL, 0, "Size options:",              xco, yco-=20, 114, 19, 0, 0.0, 0.0, 0, 0, "");
-       uiDefButS(block, NUM, 0, "X:",          xco+19, yco-=20, 95, 19,                &G.scene->r.xplay, 10.0, 2000.0, 0, 0, "Displays current X screen/window resolution. Click to change.");
-       uiDefButS(block, NUM, 0, "Y:",          xco+19, yco-=20, 95, 19, &G.scene->r.yplay, 10.0, 2000.0, 0, 0, "Displays current Y screen/window resolution. Click to change.");
-
-       uiDefBut(block, SEPR, 0, "",            xco, yco-=4, 114, 4, NULL, 0.0, 0.0, 0, 0, "");
-
-       uiDefBut(block, LABEL, 0, "Fullscreen options:",                xco, yco-=20, 114, 19, 0, 0.0, 0.0, 0, 0, "");
-       uiDefButS(block, TOG, 0, "Fullscreen", xco + 19, yco-=20, 95, 19, &G.scene->r.fullscreen, 0.0, 0.0, 0, 0, "Starts player in a new fullscreen display");
-       uiDefButS(block, NUM, 0, "Freq:",       xco+19, yco-=20, 95, 19, &G.scene->r.freqplay, 10.0, 120.0, 0, 0, "Displays clock frequency of fullscreen display. Click to change.");
-       uiDefButS(block, NUM, 0, "Bits:",       xco+19, yco-=20, 95, 19, &G.scene->r.depth, 1.0, 32.0, 0, 0, "Displays bit depth of full screen display. Click to change.");
-
-       uiDefBut(block, SEPR, 0, "",            xco, yco-=4, 114, 4, NULL, 0.0, 0.0, 0, 0, "");
-
-       /* stereo settings */
-       /* can't use any definition from the game engine here so hardcode it. Change it here when it changes there!
-        * RAS_IRasterizer has definitions:
-        * RAS_STEREO_NOSTEREO           1
-        * RAS_STEREO_QUADBUFFERED 2
-        * RAS_STEREO_ABOVEBELOW         3
-        * RAS_STEREO_INTERLACED         4       future
-        */
-       uiDefBut(block, LABEL, 0, "Stereo options", xco, yco-=20, 114, 19, 0, 0.0, 0.0, 0, 0, "");
-       uiDefButS(block, ROW, 0, "no stereo", xco+19, yco-=20, 95, 19, &(G.scene->r.stereomode), 6.0, 1.0, 0, 0, "Disables stereo");
-       uiDefButS(block, ROW, 0, "h/w pageflip", xco+19, yco-=20, 95, 19, &(G.scene->r.stereomode), 6.0, 2.0, 0, 0, "Enables hardware pageflip stereo method");
-       uiDefButS(block, ROW, 0, "syncdoubling", xco+19, yco-=20, 95, 19, &(G.scene->r.stereomode), 6.0, 3.0, 0, 0, "Enables syncdoubling stereo method");
-
-       uiBlockSetDirection(block, UI_RIGHT);
-       uiTextBoundsBlock(block, 50);
-               
-       return block;
-}
-#endif
-
-#endif
 
 static void do_info_file_importmenu(void *arg, int event)
 {
@@ -899,6 +810,10 @@ static void do_info_filemenu(void *arg, int event)
        case 31: /* save default settings */
                BIF_write_homefile();
                break;
+
+       case 35: /* compress toggle */
+               U.flag ^= (USER_FILECOMPRESS);
+               break;
        }
        allqueue(REDRAWINFO, 0);
 }
@@ -921,6 +836,12 @@ static uiBlock *info_filemenu(void *arg_unused)
 
        uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save|Ctrl W",                            0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
        uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save As...|F2",                  0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
+       
+       if(U.flag & USER_FILECOMPRESS) {
+               uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Compress File",     0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 35, "Enable file compression");
+       } else {
+               uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Compress File",   0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 35, "Enable file compression");
+       }
 
        uiDefBut(block, SEPR, 0, "",                                    0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
 
index d81f67d0440d75b0df215cbfb004ce2b5976fe38..979644f04575ecca57d381b7f86cdb6245cdee02 100644 (file)
@@ -475,6 +475,7 @@ static void do_history(char *name)
 void BIF_write_file(char *target)
 {
        Library *li;
+       int writeflags;
        char di[FILE_MAXDIR];
        char *err;
        
@@ -511,8 +512,13 @@ void BIF_write_file(char *target)
        waitcursor(1);  // exit_editmode sets cursor too
 
        do_history(di);
-               
-       if (BLO_write_file(di, G.fileflags, &err)) {
+       
+       /* we use the UserDef to define compression flag */
+       writeflags= G.fileflags & ~G_FILE_COMPRESS;
+       if(U.flag & USER_FILECOMPRESS)
+               writeflags |= G_FILE_COMPRESS;
+       
+       if (BLO_write_file(di, writeflags, &err)) {
                strcpy(G.sce, di);
                strcpy(G.main->name, di);       /* is guaranteed current file */