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