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