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