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