- changed back SHGetFolderPath to SHGetSpecialFolderPath to support older Win98 and...
[blender.git] / source / blender / src / usiblender.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33         /* placed up here because of crappy
34          * winsock stuff.
35          */
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <string.h>
39
40 #ifdef WIN32
41 #include <windows.h> /* need to include windows.h so _WIN32_IE is defined  */
42 #ifndef _WIN32_IE
43 #define _WIN32_IE 0x0400 /* minimal requirements for SHGetSpecialFolderPath on MINGW MSVC has this defined already */
44 #endif
45 #include <shlobj.h> /* for SHGetSpecialFolderPath, has to be done before BLI_winstuff because 'near' is disabled through BLI_windstuff */
46 #include "BLI_winstuff.h"
47 #include <process.h> /* getpid */
48 #else
49 #include <unistd.h> /* getpid */
50 #endif
51 #include "MEM_guardedalloc.h"
52 #include "MEM_CacheLimiterC-Api.h"
53
54 #include "BMF_Api.h"
55 #ifdef INTERNATIONAL
56 #include "BIF_language.h"
57 #include "FTF_Api.h"
58 #endif
59
60 #include "BLI_blenlib.h"
61 #include "BLI_arithb.h"
62 #include "BLI_linklist.h"
63
64 #include "IMB_imbuf_types.h"
65 #include "IMB_imbuf.h"
66
67 #include "DNA_object_types.h"
68 #include "DNA_space_types.h"
69 #include "DNA_userdef_types.h"
70 #include "DNA_sound_types.h"
71 #include "DNA_scene_types.h"
72
73 #include "BKE_blender.h"
74 #include "BKE_curve.h"
75 #include "BKE_displist.h"
76 #include "BKE_exotic.h"
77 #include "BKE_font.h"
78 #include "BKE_global.h"
79 #include "BKE_main.h"
80 #include "BKE_mball.h"
81 #include "BKE_packedFile.h"
82 #include "BKE_utildefines.h"
83
84 #include "BLI_vfontdata.h"
85
86 #include "BIF_fsmenu.h"
87 #include "BIF_gl.h"
88 #include "BIF_interface.h"
89 #include "BIF_usiblender.h"
90 #include "BIF_drawtext.h"
91 #include "BIF_editarmature.h"
92 #include "BIF_editlattice.h"
93 #include "BIF_editfont.h"
94 #include "BIF_editmesh.h"
95 #include "BIF_editmode_undo.h"
96 #include "BIF_editsound.h"
97 #include "BIF_poseobject.h"
98 #include "BIF_previewrender.h"
99 #include "BIF_renderwin.h"
100 #include "BIF_resources.h"
101 #include "BIF_screen.h"
102 #include "BIF_space.h"
103 #include "BIF_toolbox.h"
104 #include "BIF_cursors.h"
105
106 #include "BSE_drawview.h"
107 #include "BSE_edit.h"
108 #include "BSE_editipo.h"
109 #include "BSE_filesel.h"
110 #include "BSE_headerbuttons.h"
111 #include "BSE_node.h"
112
113 #include "BLO_readfile.h"
114 #include "BLO_writefile.h"
115
116 #include "BDR_drawobject.h"
117 #include "BDR_editobject.h"
118 #include "BDR_editcurve.h"
119 #include "BDR_vpaint.h"
120
121 #include "BPY_extern.h"
122
123 #include "blendef.h"
124
125 #include "RE_pipeline.h"                /* RE_ free stuff */
126
127 #include "radio.h"
128 #include "datatoc.h"
129
130 #include "SYS_System.h"
131
132 #include "PIL_time.h"
133
134 /***/
135
136 /* define for setting colors in theme below */
137 #define SETCOL(col, r, g, b, a)  col[0]=r; col[1]=g; col[2]= b; col[3]= a;
138
139 /* patching UserDef struct, set globals for UI stuff */
140 static void init_userdef_file(void)
141 {
142         
143         BIF_InitTheme();        // sets default again
144         
145         mainwindow_set_filename_to_title("");   // empty string re-initializes title to "Blender"
146         countall();
147         G.save_over = 0;        // start with save preference untitled.blend
148         
149         /*  disable autoplay in .B.blend... */
150         G.fileflags &= ~G_FILE_AUTOPLAY;
151         
152         /* the UserDef struct is not corrected with do_versions() .... ugh! */
153         if(U.wheellinescroll == 0) U.wheellinescroll = 3;
154         if(U.menuthreshold1==0) {
155                 U.menuthreshold1= 5;
156                 U.menuthreshold2= 2;
157         }
158         if(U.tb_leftmouse==0) {
159                 U.tb_leftmouse= 5;
160                 U.tb_rightmouse= 5;
161         }
162         if(U.mixbufsize==0) U.mixbufsize= 2048;
163         if (BLI_streq(U.tempdir, "/")) {
164                 char *tmp= getenv("TEMP");
165                 
166                 strcpy(U.tempdir, tmp?tmp:"/tmp/");
167         }
168         if (U.savetime <= 0) {
169                 U.savetime = 1;
170                 error(".B.blend is buggy, please consider removing it.\n");
171         }
172         /* transform widget settings */
173         if(U.tw_hotspot==0) {
174                 U.tw_hotspot= 14;
175                 U.tw_size= 20;                  // percentage of window size
176                 U.tw_handlesize= 16;    // percentage of widget radius
177         }
178         
179         if (G.main->versionfile <= 191) {
180                 strcpy(U.plugtexdir, U.textudir);
181                 strcpy(U.sounddir, "/");
182         }
183         
184         /* patch to set Dupli Armature */
185         if (G.main->versionfile < 220) {
186                 U.dupflag |= USER_DUP_ARM;
187         }
188         
189         /* userdef new option */
190         if (G.main->versionfile <= 222) {
191                 U.vrmlflag= USER_VRML_LAYERS;
192         }
193         
194         /* added seam, normal color, undo */
195         if (G.main->versionfile <= 234) {
196                 bTheme *btheme;
197                 
198                 U.uiflag |= USER_GLOBALUNDO;
199                 
200                 for(btheme= U.themes.first; btheme; btheme= btheme->next) {
201                         /* check for alpha==0 is safe, then color was never set */
202                         if(btheme->tv3d.edge_seam[3]==0) {
203                                 SETCOL(btheme->tv3d.edge_seam, 230, 150, 50, 255);
204                         }
205                         if(btheme->tv3d.normal[3]==0) {
206                                 SETCOL(btheme->tv3d.normal, 0x22, 0xDD, 0xDD, 255);
207                         }
208                         if(btheme->tv3d.face_dot[3]==0) {
209                                 SETCOL(btheme->tv3d.face_dot, 255, 138, 48, 255);
210                                 btheme->tv3d.facedot_size= 4;
211                         }
212                 }
213         }
214         if (G.main->versionfile <= 235) {
215                 /* illegal combo... */
216                 if (U.flag & USER_LMOUSESELECT) 
217                         U.flag &= ~USER_TWOBUTTONMOUSE;
218         }
219         if (G.main->versionfile <= 236) {
220                 bTheme *btheme;
221                 /* new space type */
222                 for(btheme= U.themes.first; btheme; btheme= btheme->next) {
223                         /* check for alpha==0 is safe, then color was never set */
224                         if(btheme->ttime.back[3]==0) {
225                                 btheme->ttime = btheme->tsnd;   // copy from sound
226                         }
227                         if(btheme->text.syntaxn[3]==0) {
228                                 SETCOL(btheme->text.syntaxn,    0, 0, 200, 255);        /* Numbers  Blue*/
229                                 SETCOL(btheme->text.syntaxl,    100, 0, 0, 255);        /* Strings  red */
230                                 SETCOL(btheme->text.syntaxc,    0, 100, 50, 255);       /* Comments greenish */
231                                 SETCOL(btheme->text.syntaxv,    95, 95, 0, 255);        /* Special */
232                                 SETCOL(btheme->text.syntaxb,    128, 0, 80, 255);       /* Builtin, red-purple */
233                         }
234                 }
235         }
236         if (G.main->versionfile <= 237) {
237                 bTheme *btheme;
238                 /* bone colors */
239                 for(btheme= U.themes.first; btheme; btheme= btheme->next) {
240                         /* check for alpha==0 is safe, then color was never set */
241                         if(btheme->tv3d.bone_solid[3]==0) {
242                                 SETCOL(btheme->tv3d.bone_solid, 200, 200, 200, 255);
243                                 SETCOL(btheme->tv3d.bone_pose, 80, 200, 255, 80);
244                         }
245                 }
246         }
247         if (G.main->versionfile <= 238) {
248                 bTheme *btheme;
249                 /* bone colors */
250                 for(btheme= U.themes.first; btheme; btheme= btheme->next) {
251                         /* check for alpha==0 is safe, then color was never set */
252                         if(btheme->tnla.strip[3]==0) {
253                                 SETCOL(btheme->tnla.strip_select,       0xff, 0xff, 0xaa, 255);
254                                 SETCOL(btheme->tnla.strip, 0xe4, 0x9c, 0xc6, 255);
255                         }
256                 }
257         }
258         if (G.main->versionfile <= 239) {
259                 bTheme *btheme;
260                 
261                 for(btheme= U.themes.first; btheme; btheme= btheme->next) {
262                         /* Lamp theme, check for alpha==0 is safe, then color was never set */
263                         if(btheme->tv3d.lamp[3]==0) {
264                                 SETCOL(btheme->tv3d.lamp,       0, 0, 0, 40);
265 /* TEMPORAL, remove me! (ton) */                                
266                                 U.uiflag |= USER_PLAINMENUS;
267                         }
268                         
269                         /* check for text field selection highlight, set it to text editor highlight by default */
270                         if(btheme->tui.textfield_hi[3]==0) {
271                                 SETCOL(btheme->tui.textfield_hi,        
272                                         btheme->text.shade2[0], 
273                                         btheme->text.shade2[1], 
274                                         btheme->text.shade2[2],
275                                         255);
276                         }
277                 }
278                 if(U.obcenter_dia==0) U.obcenter_dia= 6;
279         }
280         if (G.main->versionfile <= 241) {
281                 bTheme *btheme;
282                 for(btheme= U.themes.first; btheme; btheme= btheme->next) {
283                         /* Node editor theme, check for alpha==0 is safe, then color was never set */
284                         if(btheme->tnode.syntaxn[3]==0) {
285                                 /* re-uses syntax color storage */
286                                 btheme->tnode= btheme->tv3d;
287                                 SETCOL(btheme->tnode.edge_select, 255, 255, 255, 255);
288                                 SETCOL(btheme->tnode.syntaxl, 150, 150, 150, 255);      /* TH_NODE, backdrop */
289                                 SETCOL(btheme->tnode.syntaxn, 95, 110, 145, 255);       /* in/output */
290                                 SETCOL(btheme->tnode.syntaxb, 135, 125, 120, 255);      /* operator */
291                                 SETCOL(btheme->tnode.syntaxv, 120, 120, 120, 255);      /* generator */
292                                 SETCOL(btheme->tnode.syntaxc, 120, 145, 120, 255);      /* group */
293                         }
294                         if(btheme->tv3d.group[3]==0) {
295                                 SETCOL(btheme->tv3d.group, 0x10, 0x40, 0x10, 255);
296                                 SETCOL(btheme->tv3d.group_active, 0x66, 0xFF, 0x66, 255);
297                         }
298                         if(btheme->tseq.movie[3]==0) {
299                                 SETCOL(btheme->tseq.movie,      81, 105, 135, 255);
300                                 SETCOL(btheme->tseq.image,      109, 88, 129, 255);
301                                 SETCOL(btheme->tseq.scene,      78, 152, 62, 255);
302                                 SETCOL(btheme->tseq.audio,      46, 143, 143, 255);
303                                 SETCOL(btheme->tseq.effect,     169, 84, 124, 255);
304                                 SETCOL(btheme->tseq.plugin,     126, 126, 80, 255);
305                                 SETCOL(btheme->tseq.transition, 162, 95, 111, 255);
306                                 SETCOL(btheme->tseq.meta,       109, 145, 131, 255);
307                         }
308                 }
309                 
310                 /* set defaults for 3D View rotating axis indicator */ 
311                 /* since size can't be set to 0, this indicates it's not saved in .B.blend */
312                 if (U.rvisize == 0) {
313                         U.rvisize = 15;
314                         U.rvibright = 8;
315                         U.uiflag |= USER_SHOW_ROTVIEWICON;
316                 }
317                 
318         }
319         
320         if (U.undosteps==0) U.undosteps=32;
321         
322         /* GL Texture Garbage Collection (variable abused above!) */
323         if (U.textimeout == 0) {
324                 U.texcollectrate = 60;
325                 U.textimeout = 120;
326         }
327         if (U.memcachelimit <= 0) {
328                 U.memcachelimit = 32;
329         }
330         if (U.frameserverport == 0) {
331                 U.frameserverport = 8080;
332         }
333
334         MEM_CacheLimiter_set_maximum(U.memcachelimit * 1024 * 1024);
335         
336         reset_autosave();
337         
338 #ifdef INTERNATIONAL
339         read_languagefile();
340         
341         refresh_interface_font();
342 #endif // INTERNATIONAL
343
344 }
345
346 void BIF_read_file(char *name)
347 {
348         extern short winqueue_break; /* editscreen.c */
349
350         //here?
351         //sound_end_all_sounds();
352
353         // first try to read exotic file formats...
354         if (BKE_read_exotic(name) == 0) { /* throws first error box */
355                 /* we didn't succeed, now try to read Blender file
356                    calls readfile, calls toolbox, throws one more,
357                    on failure calls the stream, and that is stubbed.... */
358                 int retval= BKE_read_file(name, NULL);
359
360                 mainwindow_set_filename_to_title(G.main->name);
361                 countall();
362                 sound_initialize_sounds();
363
364                 winqueue_break= 1;      /* leave queues everywhere */
365
366                 if(retval==2) init_userdef_file();      // in case a userdef is read from regular .blend
367                 
368                 undo_editmode_clear();
369                 BKE_reset_undo();
370                 BKE_write_undo("original");     /* save current state */
371                 refresh_interface_font();
372         }
373         else BIF_undo_push("Import file");
374 }
375
376 /* only here settings for fullscreen */
377 int BIF_read_homefile(void)
378 {
379         char tstr[FILE_MAXDIR+FILE_MAXFILE], scestr[FILE_MAXDIR];
380         char *home= BLI_gethome();
381         int success;
382         struct TmpFont *tf;
383         
384         BLI_clean(home);
385
386         tf= G.ttfdata.first;
387         while(tf)
388         {
389                 freePackedFile(tf->pf);
390                 tf->pf = NULL;
391                 tf->vfont = NULL;
392                 tf= tf->next;
393         }
394         BLI_freelistN(&G.ttfdata);
395         
396 #if 0
397 //#ifdef _WIN32 // FULLSCREEN
398         static int screenmode = -1;
399         
400         screenmode = U.uiflag & USER_FLIPFULLSCREEN;
401 #endif
402         
403         BLI_make_file_string(G.sce, tstr, home, ".B.blend");
404         strcpy(scestr, G.sce);  /* temporal store */
405         
406         /* prevent loading no UI */
407         G.fileflags &= ~G_FILE_NO_UI;
408         
409         if (BLI_exists(tstr)) {
410                 success = BKE_read_file(tstr, NULL);
411         } else {
412                 success = BKE_read_file_from_memory(datatoc_B_blend, datatoc_B_blend_size, NULL);
413         }
414
415         BLI_clean(scestr);
416         strcpy(G.sce, scestr);
417         
418 #if 0
419 //#ifdef _WIN32 // FULLSCREEN
420         /* choose window startmode */
421         switch (G.windowstate){
422                 case G_WINDOWSTATE_USERDEF: /* use the usersetting */
423                         break;
424                 case G_WINDOWSTATE_FULLSCREEN: /* force fullscreen */
425                         U.uiflag |= USER_FLIPFULLSCREEN;
426                         break;
427                 case G_WINDOWSTATE_BORDER: /* force with borders */
428                         U.uiflag &= ~USER_FLIPFULLSCREEN;
429         }
430         
431         if(screenmode != (U.uiflag & USER_FLIPFULLSCREEN)) {
432                 mainwindow_toggle_fullscreen ((U.uiflag & USER_FLIPFULLSCREEN));
433                 screenmode = (U.uiflag & USER_FLIPFULLSCREEN);
434         }
435 #endif
436         
437         space_set_commmandline_options();
438         
439         init_userdef_file();
440
441         undo_editmode_clear();
442         BKE_reset_undo();
443         BKE_write_undo("original");     /* save current state */
444         
445         return success;
446 }
447
448
449 static void get_autosave_location(char buf[FILE_MAXDIR+FILE_MAXFILE])
450 {
451         char pidstr[32];
452
453         sprintf(pidstr, "%d.blend", abs(getpid()));
454         BLI_make_file_string("/", buf, U.tempdir, pidstr);
455 }
456
457 void BIF_read_autosavefile(void)
458 {
459         char tstr[FILE_MAXDIR+FILE_MAXFILE], scestr[FILE_MAXDIR];
460         int save_over;
461
462         strcpy(scestr, G.sce);  /* temporal store */
463         
464         get_autosave_location(tstr);
465
466         save_over = G.save_over;
467         BKE_read_file(tstr, NULL);
468         G.save_over = save_over;
469         strcpy(G.sce, scestr);
470 }
471
472 /* free strings of open recent files */
473 static void free_openrecent(void)
474 {
475         struct RecentFile *recent;
476
477         for(recent = G.recent_files.first; recent; recent=recent->next)
478                 MEM_freeN(recent->filename);
479
480         BLI_freelistN(&(G.recent_files));
481 }
482
483 static void readBlog(void)
484 {
485         char name[FILE_MAXDIR+FILE_MAXFILE], filename[FILE_MAXFILE];
486         LinkNode *l, *lines;
487         struct RecentFile *recent;
488         char *line;
489         int num;
490
491         BLI_make_file_string("/", name, BLI_gethome(), ".Blog");
492         lines= BLI_read_file_as_lines(name);
493
494         G.recent_files.first = G.recent_files.last = NULL;
495
496         /* read list of recent opend files from .Blog to memory */
497         for (l= lines, num= 0; l && (num<10); l= l->next, num++) {
498                 line = l->link;
499                 if (!BLI_streq(line, "")) {
500                         if (num==0) strcpy(G.sce, line);
501                         recent = (RecentFile*)MEM_mallocN(sizeof(RecentFile),"RecentFile");
502                         BLI_addtail(&(G.recent_files), recent);
503                         recent->filename = (char*)MEM_mallocN(sizeof(char)*(strlen(line)+1), "name of file");
504                         recent->filename[0] = '\0';
505                         strcpy(recent->filename, line);
506                 }
507         }
508
509         if(G.sce[0] == 0)
510                 BLI_make_file_string("/", G.sce, BLI_gethome(), "untitled.blend");
511         
512         BLI_free_file_lines(lines);
513
514 #ifdef WIN32
515         /* Add the drive names to the listing */
516         {
517                 __int64 tmp;
518                 char folder[MAX_PATH];
519                 char tmps[4];
520                 int i;
521                         
522                 tmp= GetLogicalDrives();
523                 
524                 for (i=2; i < 26; i++) {
525                         if ((tmp>>i) & 1) {
526                                 tmps[0]='a'+i;
527                                 tmps[1]=':';
528                                 tmps[2]='\\';
529                                 tmps[3]=0;
530                                 
531                                 fsmenu_insert_entry(tmps, 0);
532                         }
533                 }
534
535                 /* Adding Desktop and My Documents */
536                 fsmenu_append_seperator();
537
538                 SHGetSpecialFolderPath(0, folder, CSIDL_PERSONAL, 0);
539                 fsmenu_insert_entry(folder, 0);
540                 SHGetSpecialFolderPath(0, folder, CSIDL_DESKTOPDIRECTORY, 0);
541                 fsmenu_insert_entry(folder, 0);
542
543                 fsmenu_append_seperator();
544         }
545 #endif
546
547         BLI_make_file_string(G.sce, name, BLI_gethome(), ".Bfs");
548         lines= BLI_read_file_as_lines(name);
549
550         for (l= lines; l; l= l->next) {
551                 char *line= l->link;
552                         
553                 if (!BLI_streq(line, "")) {
554                         fsmenu_insert_entry(line, 0);
555                 }
556         }
557
558         fsmenu_append_seperator();
559         
560         /* add last saved file */
561         BLI_split_dirfile(G.sce, name, filename);
562         
563         fsmenu_insert_entry(name, 0);
564         
565         BLI_free_file_lines(lines);
566 }
567
568
569 static void writeBlog(void)
570 {
571         struct RecentFile *recent, *next_recent;
572         char name[FILE_MAXDIR+FILE_MAXFILE];
573         FILE *fp;
574         int i;
575
576         BLI_make_file_string("/", name, BLI_gethome(), ".Blog");
577
578         recent = G.recent_files.first;
579         /* refresh .Blog of recent opened files, when current file was changed */
580         if(!(recent) || (strcmp(recent->filename, G.sce)!=0)) {
581                 fp= fopen(name, "w");
582                 if (fp) {
583                         /* add current file to the beginning of list */
584                         recent = (RecentFile*)MEM_mallocN(sizeof(RecentFile),"RecentFile");
585                         recent->filename = (char*)MEM_mallocN(sizeof(char)*(strlen(G.sce)+1), "name of file");
586                         recent->filename[0] = '\0';
587                         strcpy(recent->filename, G.sce);
588                         BLI_addhead(&(G.recent_files), recent);
589                         /* write current file to .Blog */
590                         fprintf(fp, "%s\n", recent->filename);
591                         recent = recent->next;
592                         i=1;
593                         /* write rest of recent opened files to .Blog */
594                         while((i<10) && (recent)){
595                                 /* this prevents to have duplicities in list */
596                                 if (strcmp(recent->filename, G.sce)!=0) {
597                                         fprintf(fp, "%s\n", recent->filename);
598                                         recent = recent->next;
599                                 }
600                                 else {
601                                         next_recent = recent->next;
602                                         MEM_freeN(recent->filename);
603                                         BLI_freelinkN(&(G.recent_files), recent);
604                                         recent = next_recent;
605                                 }
606                                 i++;
607                         }
608                 }
609                 fclose(fp);
610         }
611 }
612
613 static void do_history(char *name)
614 {
615         char tempname1[FILE_MAXDIR+FILE_MAXFILE], tempname2[FILE_MAXDIR+FILE_MAXFILE];
616         int hisnr= U.versions;
617         
618         if(U.versions==0) return;
619         if(strlen(name)<2) return;
620                 
621         while(  hisnr > 1) {
622                 sprintf(tempname1, "%s%d", name, hisnr-1);
623                 sprintf(tempname2, "%s%d", name, hisnr);
624         
625                 if(BLI_rename(tempname1, tempname2))
626                         error("Unable to make version backup");
627                         
628                 hisnr--;
629         }
630                 
631         /* is needed when hisnr==1 */
632         sprintf(tempname1, "%s%d", name, hisnr);
633         
634         if(BLI_rename(name, tempname1))
635                 error("Unable to make version backup");
636 }
637
638 void BIF_write_file(char *target)
639 {
640         Library *li;
641         int writeflags;
642         char di[FILE_MAXDIR];
643         char *err;
644         
645         if (BLI_streq(target, "")) return;
646  
647         /* send the OnSave event */
648         if (G.f & G_DOSCRIPTLINKS) BPY_do_pyscript(&G.scene->id, SCRIPT_ONSAVE);
649
650         for (li= G.main->library.first; li; li= li->id.next) {
651                 if (BLI_streq(li->name, target)) {
652                         error("Cannot overwrite used library");
653                         return;
654                 }
655         }
656         
657         if (!BLO_has_bfile_extension(target)) {
658                 sprintf(di, "%s.blend", target);
659         } else {
660                 strcpy(di, target);
661         }
662
663         if (BLI_exists(di)) {
664                 if(!saveover(di))
665                         return; 
666         }
667         
668         if(G.obedit) {
669                 exit_editmode(0);       /* 0 = no free data */
670         }
671         if (G.fileflags & G_AUTOPACK) {
672                 packAll();
673         }
674         
675         waitcursor(1);  // exit_editmode sets cursor too
676
677         do_history(di);
678         
679         /* we use the UserDef to define compression flag */
680         writeflags= G.fileflags & ~G_FILE_COMPRESS;
681         if(U.flag & USER_FILECOMPRESS)
682                 writeflags |= G_FILE_COMPRESS;
683         
684         if (BLO_write_file(di, writeflags, &err)) {
685                 strcpy(G.sce, di);
686                 strcpy(G.main->name, di);       /* is guaranteed current file */
687
688                 mainwindow_set_filename_to_title(G.main->name);
689
690                 G.save_over = 1;
691
692                 writeBlog();
693         } else {
694                 error("%s", err);
695         }
696
697         waitcursor(0);
698 }
699
700 void BIF_write_homefile(void)
701 {
702         char *err, tstr[FILE_MAXDIR+FILE_MAXFILE];
703         int write_flags;
704         
705         BLI_make_file_string("/", tstr, BLI_gethome(), ".B.blend");
706                 
707         /*  force save as regular blend file */
708         write_flags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_LOCK | G_FILE_SIGN);
709         BLO_write_file(tstr, write_flags, &err);
710 }
711
712 void BIF_write_autosave(void)
713 {
714         char *err, tstr[FILE_MAXDIR+FILE_MAXFILE];
715         int write_flags;
716         
717         get_autosave_location(tstr);
718
719                 /*  force save as regular blend file */
720         write_flags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_LOCK | G_FILE_SIGN);
721         BLO_write_file(tstr, write_flags, &err);
722 }
723
724 /* if global undo; remove tempsave, otherwise rename */
725 static void delete_autosave(void)
726 {
727         char tstr[FILE_MAXDIR+FILE_MAXFILE];
728         
729         get_autosave_location(tstr);
730
731         if (BLI_exists(tstr)) {
732                 char str[FILE_MAXDIR+FILE_MAXFILE];
733                 BLI_make_file_string("/", str, U.tempdir, "quit.blend");
734
735                 if(U.uiflag & USER_GLOBALUNDO) BLI_delete(tstr, 0, 0);
736                 else BLI_rename(tstr, str);
737         }
738 }
739
740 /***/
741
742 static void initbuttons(void)
743 {
744         uiDefFont(UI_HELVB, 
745                                 BMF_GetFont(BMF_kHelveticaBold14), 
746                                 BMF_GetFont(BMF_kHelveticaBold12), 
747                                 BMF_GetFont(BMF_kHelveticaBold10), 
748                                 BMF_GetFont(BMF_kHelveticaBold8));
749         uiDefFont(UI_HELV, 
750                                 BMF_GetFont(BMF_kHelvetica12), 
751                                 BMF_GetFont(BMF_kHelvetica12), 
752                                 BMF_GetFont(BMF_kHelvetica10), 
753                                 BMF_GetFont(BMF_kHelveticaBold8));
754         
755         BIF_resources_init();
756
757         glClearColor(.7f, .7f, .6f, 0.0);
758         
759         G.font= BMF_GetFont(BMF_kHelvetica12);
760         G.fonts= BMF_GetFont(BMF_kHelvetica10);
761         G.fontss= BMF_GetFont(BMF_kHelveticaBold8);
762
763         clear_matcopybuf();
764         
765         glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
766 }
767
768
769 static void sound_init_listener(void)
770 {
771         G.listener = MEM_callocN(sizeof(bSoundListener), "soundlistener");
772         G.listener->gain = 1.0;
773         G.listener->dopplerfactor = 1.0;
774         G.listener->dopplervelocity = 340.29f;
775 }
776
777 void BIF_init(void)
778 {
779
780         initscreen();   /* for (visuele) speed, this first, then setscreen */
781         initbuttons();
782         InitCursorData();
783         sound_init_listener();
784         init_node_butfuncs();
785         
786         BIF_preview_init_dbase();
787         BIF_read_homefile();
788         
789         init_gl_stuff();        /* drawview.c, after homefile */
790         readBlog();
791         strcpy(G.lib, G.sce);
792
793 }
794
795 /***/
796
797 extern ListBase editNurb;
798 extern ListBase editelems;
799
800 void exit_usiblender(void)
801 {
802         struct TmpFont *tf;
803         tf= G.ttfdata.first;
804         while(tf)
805         {
806                 freePackedFile(tf->pf);
807                 tf->pf= NULL;
808                 tf->vfont= NULL;
809                 tf= tf->next;
810         }
811         BLI_freelistN(&G.ttfdata);
812         free_openrecent();
813
814         freeAllRad();
815         BKE_freecubetable();
816
817         if (G.background == 0)
818                 sound_end_all_sounds();
819
820         if(G.obedit) {
821                 if(G.obedit->type==OB_FONT) {
822                         free_editText();
823                 }
824                 else if(G.obedit->type==OB_MBALL) BLI_freelistN(&editelems);
825                 free_editMesh(G.editMesh);
826         }
827
828         free_editLatt();
829         free_editArmature();
830         free_posebuf();
831
832         /* before free_blender so py's gc happens while library still exists */
833         /* needed at least for a rare sigsegv that can happen in pydrivers */
834         BPY_end_python();
835
836         fastshade_free_render();        /* shaded view */
837         free_blender();                         /* blender.c, does entire library */
838         free_matcopybuf();
839         free_ipocopybuf();
840         free_vertexpaint();
841         
842         /* editnurb can remain to exist outside editmode */
843         freeNurblist(&editNurb);
844
845         fsmenu_free();
846 #ifdef INTERNATIONAL
847         free_languagemenu();
848 #endif  
849         
850         RE_FreeAllRender();
851         
852         free_txt_data();
853
854         sound_exit_audio();
855         if(G.listener) MEM_freeN(G.listener);
856
857         libtiff_exit();
858
859 #ifdef WITH_QUICKTIME
860         quicktime_exit();
861 #endif
862
863         if (!G.background) {
864                 BIF_resources_free();
865         
866                 BIF_close_render_display();
867                 mainwindow_close();
868         }
869
870 #ifdef INTERNATIONAL
871         FTF_End();
872 #endif
873
874         if (copybuf) MEM_freeN(copybuf);
875         if (copybufinfo) MEM_freeN(copybufinfo);
876
877         /* undo free stuff */
878         undo_editmode_clear();
879         
880         BKE_undo_save_quit();   // saves quit.blend if global undo is on
881         BKE_reset_undo(); 
882         
883         BLI_freelistN(&U.themes);
884         BIF_preview_free_dbase();
885                 
886         if(totblock!=0) {
887                 printf("Error Totblock: %d\n",totblock);
888                 MEM_printmemlist();
889         }
890         delete_autosave();
891         
892         printf("\nBlender quit\n");
893
894 #ifdef WIN32   
895         /* ask user to press enter when in debug mode */
896         if(G.f & G_DEBUG) {
897                 printf("press enter key to exit...\n\n");
898                 getchar();
899         }
900 #endif 
901
902
903         SYS_DeleteSystem(SYS_GetSystem());
904
905         exit(G.afbreek==1);
906 }