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