This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/src/filesel.c
Kent Mein d0e346d544 updated .c files to include:
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

Just need to finish cpp files now :)

Kent
--
mein@cs.umn.edu
2002-11-25 12:02:15 +00:00

2381 lines
53 KiB
C

/**
* $Id$
*
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version. The Blender
* Foundation also sells licenses for use in proprietary software under
* the Blender License. See http://www.blender.org/BL/ for information
* about this.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
#include <stdlib.h>
#include <string.h>
#include <math.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef WIN32
#include <io.h>
#include <direct.h>
#include "BLI_winstuff.h"
#else
#include <unistd.h>
#include <sys/times.h>
#endif
#include <sys/stat.h>
#include <sys/types.h>
#include "MEM_guardedalloc.h"
#include "BMF_Api.h"
#include "BLI_blenlib.h"
#include "BLI_arithb.h"
#include "BLI_editVert.h"
#include "BLI_linklist.h"
#include "BLI_storage_types.h"
#include "BLI_dynstr.h"
#include "IMB_imbuf.h"
#include "DNA_curve_types.h"
#include "DNA_image_types.h"
#include "DNA_ipo_types.h"
#include "DNA_vfont_types.h"
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
#include "DNA_texture_types.h"
#include "DNA_space_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_view3d_types.h"
#include "DNA_userdef_types.h"
#include "BKE_utildefines.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_displist.h"
#include "BKE_library.h"
#include "BKE_curve.h"
#include "BKE_font.h"
#include "BKE_material.h"
#include "BIF_gl.h"
#include "BIF_interface.h"
#include "BIF_toolbox.h"
#include "BIF_mywindow.h"
#include "BIF_editview.h"
#include "BIF_space.h"
#include "BIF_screen.h"
#include "BLO_readfile.h"
#include "BDR_editcurve.h"
#include "BSE_filesel.h"
#include "BSE_view.h"
#include "mydevice.h"
#include "blendef.h"
#include "render.h"
#include "interface.h"
#include "nla.h"
#if defined WIN32 || defined __BeOS
int fnmatch(){return 0;}
#else
#include <fnmatch.h>
#endif
#ifndef WIN32
#include <sys/param.h>
#endif
#define FILESELHEAD 60
#define FILESEL_DY 16
#define NOTACTIVE 0
#define ACTIVATE 1
#define INACTIVATE 2
#define STARTSWITH(x, y) (strncmp(x, y, sizeof(x) - 1) == 0)
static int is_a_library(SpaceFile *sfile, char *dir, char *group);
static void do_library_append(SpaceFile *sfile);
static void library_to_filelist(SpaceFile *sfile);
static void filesel_select_objects(struct SpaceFile *sfile);
static void active_file_object(struct SpaceFile *sfile);
static int groupname_to_code(char *group);
/* local globals */
static rcti scrollrct, textrct, bar;
static int filebuty1, filebuty2, page_ofs, collumwidth, selecting=0;
static int filetoname= 0;
static float pixels_to_ofs;
static char otherdir[FILE_MAXDIR];
static ScrArea *otherarea;
/* FSMENU HANDLING */
/* FSMenuEntry's without paths indicate seperators */
typedef struct _FSMenuEntry FSMenuEntry;
struct _FSMenuEntry {
FSMenuEntry *next;
char *path;
};
static FSMenuEntry *fsmenu= 0, *lseperator= 0;
int fsmenu_get_nentries(void)
{
FSMenuEntry *fsme;
int count= 0;
for (fsme= fsmenu; fsme; fsme= fsme->next)
count++;
return count;
}
int fsmenu_is_entry_a_seperator(int idx)
{
FSMenuEntry *fsme;
for (fsme= fsmenu; fsme && idx; fsme= fsme->next)
idx--;
return (fsme && !fsme->path)?1:0;
}
char *fsmenu_get_entry(int idx)
{
FSMenuEntry *fsme;
for (fsme= fsmenu; fsme && idx; fsme= fsme->next)
idx--;
return fsme?fsme->path:NULL;
}
char *fsmenu_build_menu(void)
{
DynStr *ds= BLI_dynstr_new();
FSMenuEntry *fsme;
char *menustr;
for (fsme= fsmenu; fsme; fsme= fsme->next) {
if (!fsme->path) {
/* ignore consecutive or trailing seperators */
if (fsme->next && fsme->next->path)
BLI_dynstr_append(ds, "%l|");
} else {
BLI_dynstr_append(ds, fsme->path);
if (fsme->next) BLI_dynstr_append(ds, "|");
}
}
menustr= BLI_dynstr_get_cstring(ds);
BLI_dynstr_free(ds);
return menustr;
}
void fsmenu_insert_entry(char *path, int sorted)
{
FSMenuEntry *fsme, *prev;
if (lseperator) {
prev= lseperator;
fsme= lseperator->next;
} else {
prev= NULL;
fsme= fsmenu;
}
for (; fsme; prev= fsme, fsme= fsme->next) {
if (fsme->path) {
if (BLI_streq(path, fsme->path)) {
return;
} else if (sorted && strcmp(path, fsme->path)<0) {
break;
}
}
}
fsme= MEM_mallocN(sizeof(*fsme), "fsme");
fsme->path= BLI_strdup(path);
if (prev) {
fsme->next= prev->next;
prev->next= fsme;
} else {
fsme->next= fsmenu;
fsmenu= fsme;
}
}
void fsmenu_append_seperator(void)
{
if (fsmenu) {
FSMenuEntry *fsme= fsmenu;
while (fsme->next) fsme= fsme->next;
lseperator= MEM_mallocN(sizeof(*fsme), "fsme");
lseperator->next= NULL;
lseperator->path= NULL;
fsme->next= lseperator;
}
}
void fsmenu_remove_entry(int idx)
{
FSMenuEntry *prev= NULL, *fsme= fsmenu;
for (fsme= fsmenu; fsme && idx; prev= fsme, fsme= fsme->next)
if (fsme->path)
idx--;
if (fsme) {
if (prev) {
prev->next= fsme->next;
} else {
fsmenu= fsme->next;
}
MEM_freeN(fsme->path);
MEM_freeN(fsme);
}
}
void fsmenu_free(void)
{
FSMenuEntry *fsme= fsmenu;
while (fsme) {
FSMenuEntry *n= fsme->next;
if (fsme->path) MEM_freeN(fsme->path);
MEM_freeN(fsme);
fsme= n;
}
}
/* ******************* SORT ******************* */
static int compare_name(const void *a1, const void *a2)
{
const struct direntry *entry1=a1, *entry2=a2;
/* type is gelijk aan stat.st_mode */
if (S_ISDIR(entry1->type)){
if (S_ISDIR(entry2->type)==0) return (-1);
} else{
if (S_ISDIR(entry2->type)) return (1);
}
if (S_ISREG(entry1->type)){
if (S_ISREG(entry2->type)==0) return (-1);
} else{
if (S_ISREG(entry2->type)) return (1);
}
if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
return (strcasecmp(entry1->relname,entry2->relname));
}
static int compare_date(const void *a1, const void *a2)
{
const struct direntry *entry1=a1, *entry2=a2;
/* type is gelijk aan stat.st_mode */
if (S_ISDIR(entry1->type)){
if (S_ISDIR(entry2->type)==0) return (-1);
} else{
if (S_ISDIR(entry2->type)) return (1);
}
if (S_ISREG(entry1->type)){
if (S_ISREG(entry2->type)==0) return (-1);
} else{
if (S_ISREG(entry2->type)) return (1);
}
if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
/*
if ( entry1->s.st_ctime < entry2->s.st_ctime) return 1;
if ( entry1->s.st_ctime > entry2->s.st_ctime) return -1;
*/
if ( entry1->s.st_mtime < entry2->s.st_mtime) return 1;
if ( entry1->s.st_mtime > entry2->s.st_mtime) return -1;
else return strcasecmp(entry1->relname,entry2->relname);
}
static int compare_size(const void *a1, const void *a2)
{
const struct direntry *entry1=a1, *entry2=a2;
/* type is gelijk aan stat.st_mode */
if (S_ISDIR(entry1->type)){
if (S_ISDIR(entry2->type)==0) return (-1);
} else{
if (S_ISDIR(entry2->type)) return (1);
}
if (S_ISREG(entry1->type)){
if (S_ISREG(entry2->type)==0) return (-1);
} else{
if (S_ISREG(entry2->type)) return (1);
}
if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
if ( entry1->s.st_size < entry2->s.st_size) return 1;
if ( entry1->s.st_size > entry2->s.st_size) return -1;
else return strcasecmp(entry1->relname,entry2->relname);
}
/* **************************************** */
void clear_global_filesel_vars()
{
selecting= 0;
}
void filesel_statistics(SpaceFile *sfile, int *totfile, int *selfile, float *totlen, float *sellen)
{
int a, len;
*totfile= *selfile= 0;
*totlen= *sellen= 0;
if(sfile->filelist==0) return;
for(a=0; a<sfile->totfile; a++) {
if( (sfile->filelist[a].type & S_IFDIR)==0 ) {
(*totfile) ++;
len = sfile->filelist[a].s.st_size;
(*totlen) += (len/1048576.0);
if(sfile->filelist[a].flags & ACTIVE) {
(*selfile) ++;
(*sellen) += (len/1048576.0);
}
}
}
}
/* *************** HULPFUNKTIES ******************* */
/* This is a really ugly function... its purpose is to
* take the space file name and clean it up, replacing
* excess file entry stuff (like /tmp/../tmp/../)
*/
void checkdir(char *dir)
{
short a;
char *start, *eind;
char tmp[FILE_MAXDIR+FILE_MAXFILE];
BLI_make_file_string(G.sce, tmp, dir, "");
strcpy(dir, tmp);
#ifdef WIN32
if(dir[0]=='.') { /* komt voor, o.a. bij FILE_MAIN */
dir[0]= '\\';
dir[1]= 0;
return;
}
while (start = strstr(dir, "\\..\\")) {
eind = start + strlen("\\..\\") - 1;
a = start-dir-1;
while (a>0) {
if (dir[a] == '\\') break;
a--;
}
strcpy(dir+a,eind);
}
while (start = strstr(dir,"\\.\\")){
eind = start + strlen("\\.\\") - 1;
strcpy(start,eind);
}
while (start = strstr(dir,"\\\\" )){
eind = start + strlen("\\\\") - 1;
strcpy(start,eind);
}
if(a = strlen(dir)){ /* eerst alle '\\' weghalen aan het eind */
while(a>0 && dir[a-1] == '\\'){
a--;
dir[a] = 0;
}
}
strcat(dir, "\\");
#else
if(dir[0]=='.') { /* komt voor, o.a. bij FILE_MAIN */
dir[0]= '/';
dir[1]= 0;
return;
}
while ( (start = strstr(dir, "/../")) ) {
eind = start + strlen("/../") - 1;
a = start-dir-1;
while (a>0) {
if (dir[a] == '/') break;
a--;
}
strcpy(dir+a,eind);
}
while ( (start = strstr(dir,"/./")) ){
eind = start + strlen("/./") - 1;
strcpy(start,eind);
}
while ( (start = strstr(dir,"//" )) ){
eind = start + strlen("//") - 1;
strcpy(start,eind);
}
if( (a = strlen(dir)) ){ /* eerst alle '/' weghalen aan het eind */
while(dir[a-1] == '/'){
a--;
dir[a] = 0;
if (a<=0) break;
}
}
strcat(dir, "/");
#endif
}
void test_flags_file(SpaceFile *sfile)
{
struct direntry *file;
int num;
file= sfile->filelist;
for(num=0; num<sfile->totfile; num++, file++) {
file->flags= 0;
file->type= file->s.st_mode; /* restore het geknoei van hieronder */
/* Don't check extensions for directories */
if (file->type&S_IFDIR)
continue;
if(sfile->type==FILE_BLENDER || sfile->type==FILE_LOADLIB) {
if(BLO_has_bfile_extension(file->relname)) {
file->flags |= BLENDERFILE;
if(sfile->type==FILE_LOADLIB) {
file->type &= ~S_IFMT;
file->type |= S_IFDIR;
}
}
else if(BLI_testextensie(file->relname, ".psx")) {
file->flags |= PSXFILE;
}
} else if (sfile->type==FILE_SPECIAL){
if(BLI_testextensie(file->relname, ".jpg") ||
BLI_testextensie(file->relname, ".tga") ||
BLI_testextensie(file->relname, ".rgb") ||
BLI_testextensie(file->relname, ".png") ||
BLI_testextensie(file->relname, ".sgi")) {
file->flags |= IMAGEFILE;
}
else if(BLI_testextensie(file->relname, ".avi") ||
BLI_testextensie(file->relname, ".mv")) {
file->flags |= MOVIEFILE;
}
}
}
}
void sort_filelist(SpaceFile *sfile)
{
struct direntry *file;
int num;/* , act= 0; */
switch(sfile->sort) {
case FILE_SORTALPHA:
qsort(sfile->filelist, sfile->totfile, sizeof(struct direntry), compare_name);
break;
case FILE_SORTDATE:
qsort(sfile->filelist, sfile->totfile, sizeof(struct direntry), compare_date);
break;
case FILE_SORTSIZE:
qsort(sfile->filelist, sfile->totfile, sizeof(struct direntry), compare_size);
break;
case FILE_SORTEXTENS:
qsort(sfile->filelist, sfile->totfile, sizeof(struct direntry), compare_name);
break;
}
sfile->act= -1;
file= sfile->filelist;
for(num=0; num<sfile->totfile; num++, file++) {
file->flags &= ~HILITE;
}
}
void read_dir(SpaceFile *sfile)
{
int num, len;
char wdir[FILE_MAXDIR];
/* sfile->act wordt gebruikt o.a. bij databrowse: dubbele namen van library objecten */
sfile->act= -1;
if(sfile->type==FILE_MAIN) {
main_to_filelist(sfile);
return;
}
else if(sfile->type==FILE_LOADLIB) {
library_to_filelist(sfile);
if(sfile->libfiledata) return;
}
BLI_hide_dot_files(sfile->flag & FILE_HIDE_DOT);
BLI_getwdN(wdir);
sfile->totfile= BLI_getdir(sfile->dir, &(sfile->filelist));
chdir(wdir);
if(sfile->sort!=FILE_SORTALPHA) sort_filelist(sfile);
sfile->maxnamelen= 0;
for (num=0; num<sfile->totfile; num++) {
len = BMF_GetStringWidth(G.font, sfile->filelist[num].relname);
if (len > sfile->maxnamelen) sfile->maxnamelen = len;
if(filetoname) {
if(strcmp(sfile->file, sfile->filelist[num].relname)==0) {
sfile->ofs= num-( sfile->collums*(curarea->winy-FILESELHEAD-20)/(2*FILESEL_DY));
filetoname= 0;
}
}
}
test_flags_file(sfile);
filetoname= 0;
}
void freefilelist(SpaceFile *sfile)
{
int num;
num= sfile->totfile-1;
if (sfile->filelist==0) return;
for(; num>=0; num--){
free(sfile->filelist[num].relname);
if (sfile->filelist[num].string) free(sfile->filelist[num].string);
}
free(sfile->filelist);
sfile->filelist= 0;
}
static void split_sfile(SpaceFile *sfile, char *s1)
{
char string[FILE_MAXDIR+FILE_MAXFILE], dir[FILE_MAXDIR], file[FILE_MAXFILE];
strcpy(string, s1);
BLI_split_dirfile(string, dir, file);
if(sfile->filelist) {
if(strcmp(dir, sfile->dir)!=0) {
freefilelist(sfile);
}
else test_flags_file(sfile);
}
strcpy(sfile->file, file);
BLI_make_file_string(G.sce, sfile->dir, dir, "");
}
void parent(SpaceFile *sfile)
{
short a;
char *dir;
/* als databrowse: geen parent */
if(sfile->type==FILE_MAIN && sfile->returnfunc) return;
dir= sfile->dir;
#ifdef WIN32
if(a = strlen(dir)) { /* eerst alle '/' weghalen aan het eind */
while(dir[a-1] == '\\') {
a--;
dir[a] = 0;
if (a<=0) break;
}
}
if(a = strlen(dir)) { /* daarna alles weghalen tot aan '/' */
while(dir[a-1] != '\\') {
a--;
dir[a] = 0;
if (a<=0) break;
}
}
if (a = strlen(dir)) {
if (dir[a-1] != '\\') strcat(dir,"\\");
}
else if(sfile->type!=FILE_MAIN) strcpy(dir,"\\");
#else
if( (a = strlen(dir)) ) { /* eerst alle '/' weghalen aan het eind */
while(dir[a-1] == '/') {
a--;
dir[a] = 0;
if (a<=0) break;
}
}
if( (a = strlen(dir)) ) { /* daarna alles weghalen tot aan '/' */
while(dir[a-1] != '/') {
a--;
dir[a] = 0;
if (a<=0) break;
}
}
if ( (a = strlen(dir)) ) {
if (dir[a-1] != '/') strcat(dir,"/");
}
else if(sfile->type!=FILE_MAIN) strcpy(dir,"/");
#endif
/* to be sure */
BLI_make_exist(sfile->dir);
freefilelist(sfile);
sfile->ofs= 0;
scrarea_queue_winredraw(curarea);
}
void swapselect_file(SpaceFile *sfile)
{
struct direntry *file;
int num, act= 0;
file= sfile->filelist;
for(num=0; num<sfile->totfile; num++, file++) {
if(file->flags & ACTIVE) {
act= 1;
break;
}
}
file= sfile->filelist+2;
for(num=2; num<sfile->totfile; num++, file++) {
if(act) file->flags &= ~ACTIVE;
else file->flags |= ACTIVE;
}
}
static int find_active_file(SpaceFile *sfile, short x, short y)
{
int ofs;
if(y > textrct.ymax) y= textrct.ymax;
if(y <= textrct.ymin) y= textrct.ymin+1;
ofs= (x-textrct.xmin)/collumwidth;
if(ofs<0) ofs= 0;
ofs*= (textrct.ymax-textrct.ymin);
return sfile->ofs+ (ofs+textrct.ymax-y)/FILESEL_DY;
}
/* ********************** DRAW ******************************* */
static void calc_file_rcts(SpaceFile *sfile)
{
int tot, h, len;
float fac, start, totfile;
scrollrct.xmin= 15;
scrollrct.xmax= 35;
scrollrct.ymin= 10;
scrollrct.ymax= curarea->winy-10-FILESELHEAD;
textrct.xmin= scrollrct.xmax+10;
textrct.xmax= curarea->winx-10;
textrct.ymin= scrollrct.ymin;
textrct.ymax= scrollrct.ymax;
if(textrct.xmax-textrct.xmin <60) textrct.xmax= textrct.xmin+60;
len= (textrct.ymax-textrct.ymin) % FILESEL_DY;
textrct.ymin+= len;
scrollrct.ymin+= len;
filebuty1= curarea->winy-FILESELHEAD;
filebuty2= filebuty1+FILESELHEAD/2 -6;
/* aantal kolommen */
len= sfile->maxnamelen+25;
if(sfile->type==FILE_MAIN) len+= 100;
else if(sfile->flag & FILE_SHOWSHORT) len+= 100;
else len+= 380;
sfile->collums= (textrct.xmax-textrct.xmin)/len;
if(sfile->collums<1) sfile->collums= 1;
else if(sfile->collums>8) sfile->collums= 8;
if((U.flag & FSCOLLUM)==0) if(sfile->type!=FILE_MAIN) sfile->collums= 1;
collumwidth= (textrct.xmax-textrct.xmin)/sfile->collums;
totfile= sfile->totfile + 0.5;
tot= FILESEL_DY*totfile;
if(tot) fac= ((float)sfile->collums*(scrollrct.ymax-scrollrct.ymin))/( (float)tot);
else fac= 1.0;
if(sfile->ofs<0) sfile->ofs= 0;
if(tot) start= ( (float)sfile->ofs)/(totfile);
else start= 0.0;
if(fac>1.0) fac= 1.0;
if(start+fac>1.0) {
sfile->ofs= ceil((1.0-fac)*totfile);
start= ( (float)sfile->ofs)/(totfile);
fac= 1.0-start;
}
bar.xmin= scrollrct.xmin+2;
bar.xmax= scrollrct.xmax-2;
h= (scrollrct.ymax-scrollrct.ymin)-4;
bar.ymax= scrollrct.ymax-2- start*h;
bar.ymin= bar.ymax- fac*h;
pixels_to_ofs= (totfile)/(float)(h+3);
page_ofs= fac*totfile;
}
int filescrollselect= 0;
static void draw_filescroll(SpaceFile *sfile)
{
if(scrollrct.ymin+10 >= scrollrct.ymax) return;
cpack(0x707070);
glRecti(scrollrct.xmin, scrollrct.ymin, scrollrct.xmax, scrollrct.ymax);
uiEmboss(scrollrct.xmin, scrollrct.ymin, scrollrct.xmax, scrollrct.ymax, 1);
cpack(0x909090);
glRecti(bar.xmin+2, bar.ymin+2, bar.xmax-2, bar.ymax-2);
uiEmboss(bar.xmin+2, bar.ymin+2, bar.xmax-2, bar.ymax-2, filescrollselect);
}
static void regelrect(unsigned int col, int x, int y)
{
cpack(col);
glRects(x-17, y-3, x+collumwidth-21, y+11);
}
static void printregel(SpaceFile *sfile, struct direntry *files, int x, int y)
{
unsigned int boxcol=0;
char *s;
switch(files->flags & (HILITE + ACTIVE)) {
case HILITE+ACTIVE:
boxcol= (0xC09090);
break;
case HILITE:
boxcol= (0x909090);
break;
case ACTIVE:
boxcol= (0xB08080);
break;
}
if(boxcol) {
regelrect(boxcol, x, y);
}
if(files->flags & BLENDERFILE) {
cpack(0xA0A0);
glRects(x-14, y, x-8, y+7);
}
else if(files->flags & PSXFILE) {
cpack(0xA060B0);
glRects(x-14, y, x-8, y+7);
}
else if(files->flags & IMAGEFILE) {
cpack(0xF08040);
glRects(x-14, y, x-8, y+7);
}
else if(files->flags & MOVIEFILE) {
cpack(0x70A070);
glRects(x-14, y, x-8, y+7);
}
if(S_ISDIR(files->type)) cpack(0xFFFFFF);
else cpack(0x0);
s = files->string;
if(s) {
glRasterPos2i(x, y);
BMF_DrawString(G.font, files->relname);
x += sfile->maxnamelen + 100;
glRasterPos2i(x - BMF_GetStringWidth(G.font, files->size), y);
BMF_DrawString(G.font, files->size);
if(sfile->flag & FILE_SHOWSHORT) return;
#ifndef WIN32
/* rwx rwx rwx */
x += 20; glRasterPos2i(x, y);
BMF_DrawString(G.font, files->mode1);
x += 30; glRasterPos2i(x, y);
BMF_DrawString(G.font, files->mode2);
x += 30; glRasterPos2i(x, y);
BMF_DrawString(G.font, files->mode3);
/* owner time date */
x += 30; glRasterPos2i(x, y);
BMF_DrawString(G.font, files->owner);
#endif
x += 60; glRasterPos2i(x, y);
BMF_DrawString(G.font, files->time);
x += 50; glRasterPos2i(x, y);
BMF_DrawString(G.font, files->date);
}
else {
glRasterPos2i(x, y);
BMF_DrawString(G.font, files->relname);
if(files->nr) { /* extra info */
x+= sfile->maxnamelen+20;
glRasterPos2i(x, y);
BMF_DrawString(G.font, files->extra);
}
}
}
static int calc_filesel_regel(SpaceFile *sfile, int nr, int *valx, int *valy)
{
/* sco van de de regel */
int val, coll;
nr-= sfile->ofs;
/* aantal regels in de hoogte */
val= (textrct.ymax-textrct.ymin)/FILESEL_DY;
coll= nr/val;
nr -= coll*val;
*valy= textrct.ymax-FILESEL_DY+3 - nr*FILESEL_DY;
*valx= coll*collumwidth + textrct.xmin+20;
if(nr<0 || coll > sfile->collums) return 0;
return 1;
}
static void set_active_file(SpaceFile *sfile, int act)
{
struct direntry *file;
int num, redraw= 0, newflag;
int old=0, newi=0;
file= sfile->filelist;
if(file==0) return;
for(num=0; num<sfile->totfile; num++, file++) {
if(num==act) {
if(selecting && num>1) {
newflag= HILITE | (file->flags & ~ACTIVE);
if(selecting==ACTIVATE) newflag |= ACTIVE;
if(file->flags != newflag) redraw|= 1;
file->flags= newflag;
}
else {
if(file->flags & HILITE);
else {
file->flags |= HILITE;
redraw|= 2;
newi= num;
}
}
}
else {
if(file->flags & HILITE) {
file->flags &= ~HILITE;
redraw|= 2;
old= num;
}
}
}
if(redraw==2) {
int x, y;
glDrawBuffer(GL_FRONT);
glScissor(curarea->winrct.xmin, curarea->winrct.ymin, curarea->winx-12, curarea->winy);
if( calc_filesel_regel(sfile, old, &x, &y) ) {
regelrect(0x717171, x, y);
printregel(sfile, sfile->filelist+old, x, y);
}
if( calc_filesel_regel(sfile, newi, &x, &y) ) {
printregel(sfile, sfile->filelist+newi, x, y);
}
glScissor(curarea->winrct.xmin, curarea->winrct.ymin, curarea->winx, curarea->winy);
glFinish(); /* for geforce, to show it in the frontbuffer */
glDrawBuffer(GL_BACK);
}
else if(redraw) {
scrarea_queue_winredraw(curarea);
}
}
static void draw_filetext(SpaceFile *sfile)
{
struct direntry *files;
int a, x, y;
short mval[2];
if(textrct.ymin+10 >= textrct.ymax) return;
/* kader */
cpack(0x717171);
glRecti(textrct.xmin, textrct.ymin, textrct.xmax, textrct.ymax);
/* kolommen */
x= textrct.xmin+collumwidth;
for(a=1; a<sfile->collums; a++, x+= collumwidth) {
cpack(0x303030);
sdrawline(x, textrct.ymin, x, textrct.ymax);
cpack(0xB0B0B0);
sdrawline(x+1, textrct.ymin, x+1, textrct.ymax);
}
if(sfile->filelist==0) return;
/* test: als muis niet in area staat: de HILITE wissen */
getmouseco_areawin(mval);
if(mval[0]<0 || mval[0]>curarea->winx) {
files= sfile->filelist+sfile->ofs;
for(a= sfile->ofs; a<sfile->totfile; a++, files++) files->flags &= ~HILITE;
}
files= sfile->filelist+sfile->ofs;
for(a= sfile->ofs; a<sfile->totfile; a++, files++) {
if( calc_filesel_regel(sfile, a, &x, &y)==0 ) break;
printregel(sfile, files, x, y);
}
/* wissen tekenfoutjes, tekst teveel aan de rechterkant: */
uiEmboss(textrct.xmin, textrct.ymin, textrct.xmax, textrct.ymax, 1);
glColor3f(.5625, .5625, .5625);
glRecti(textrct.xmax+2, textrct.ymin, textrct.xmax+10, textrct.ymax);
}
void drawfilespace()
{
SpaceFile *sfile;
uiBlock *block;
int act, loadbutton;
short mval[2];
char name[20];
char *menu;
myortho2(-0.5, curarea->winrct.xmax-curarea->winrct.xmin-0.5, -0.5, curarea->winrct.ymax-curarea->winrct.ymin-0.5);
glClearColor(.56, .56, .56, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
sfile= curarea->spacedata.first;
if(sfile->filelist==0) {
read_dir(sfile);
calc_file_rcts(sfile);
/* act berekenen */
getmouseco_areawin(mval);
act= find_active_file(sfile, mval[0], mval[1]);
if(act>=0 && act<sfile->totfile)
sfile->filelist[act].flags |= HILITE;
}
else calc_file_rcts(sfile);
/* HEADER */
sprintf(name, "win %d", curarea->win);
block= uiNewBlock(&curarea->uiblocks, name, UI_EMBOSSF, UI_HELV, curarea->win);
uiSetButLock( sfile->type==FILE_MAIN && sfile->returnfunc, NULL);
/* space available for load/save buttons? */
loadbutton= MAX2(80, 20+BMF_GetStringWidth(G.font, sfile->title));
if(textrct.xmax-textrct.xmin > loadbutton+20) {
if(sfile->title[0]==0) loadbutton= 0;
}
else loadbutton= 0;
uiDefBut(block, TEX, 1,"", textrct.xmin, filebuty1, textrct.xmax-textrct.xmin-loadbutton, 21, sfile->file, 0.0, (float)FILE_MAXFILE-1, 0, 0, "");
uiDefBut(block, TEX, 2,"", textrct.xmin, filebuty2, textrct.xmax-textrct.xmin-loadbutton, 21, sfile->dir, 0.0, (float)FILE_MAXFILE-1, 0, 0, "");
if(loadbutton) {
uiSetCurFont(block, UI_HELV);
uiDefBut(block, BUT, 5, sfile->title, textrct.xmax-loadbutton, filebuty2, loadbutton, 21, sfile->dir, 0.0, (float)FILE_MAXFILE-1, 0, 0, "");
uiDefBut(block, BUT, 6, "Cancel", textrct.xmax-loadbutton, filebuty1, loadbutton, 21, sfile->file, 0.0, (float)FILE_MAXFILE-1, 0, 0, "");
}
menu= fsmenu_build_menu();
uiDefButS(block, MENU, 3, menu, scrollrct.xmin, filebuty1, scrollrct.xmax-scrollrct.xmin, 21, &sfile->menu, 0, 0, 0, 0, "");
MEM_freeN(menu);
uiDefBut(block, BUT, 4, "P", scrollrct.xmin, filebuty2, scrollrct.xmax-scrollrct.xmin, 21, 0, 0, 0, 0, 0, "Move to the parent directory (PKEY)");
draw_filescroll(sfile);
draw_filetext(sfile);
/* andere diskfree etc ? */
scrarea_queue_headredraw(curarea);
uiDrawBlock(block);
curarea->win_swap= WIN_BACK_OK;
}
static void do_filescroll(SpaceFile *sfile)
{
short mval[2], oldy, yo;
calc_file_rcts(sfile);
filescrollselect= 1;
/* voor mooiigheid */
glDrawBuffer(GL_FRONT);
draw_filescroll(sfile);
glDrawBuffer(GL_BACK);
getmouseco_areawin(mval);
oldy= yo= mval[1];
while(get_mbut()&L_MOUSE) {
getmouseco_areawin(mval);
if(yo!=mval[1]) {
int dy= floor(0.5+((float)(oldy-mval[1]))*pixels_to_ofs);
if(dy) {
sfile->ofs+= dy;
if(sfile->ofs<0) {
sfile->ofs= 0;
oldy= mval[1];
}
else oldy= floor(0.5+ (float)oldy - (float)dy/pixels_to_ofs);
scrarea_do_windraw(curarea);
screen_swapbuffers();
}
yo= mval[1];
}
else BIF_wait_for_statechange();
}
filescrollselect= 0;
/* voor mooiigheid */
glDrawBuffer(GL_FRONT);
draw_filescroll(sfile);
glDrawBuffer(GL_BACK);
}
void activate_fileselect(int type, char *title, char *file, void (*func)(char *))
{
SpaceFile *sfile;
char group[24], name[FILE_MAXDIR], temp[FILE_MAXDIR];
if(curarea==0) return;
if(curarea->win==0) return;
newspace(curarea, SPACE_FILE);
scrarea_queue_winredraw(curarea);
/* is misschien dubbelop, voor geval area al SPACE_FILE is met andere filename */
addqueue(curarea->headwin, CHANGED, 1);
name[2]= 0;
strcpy(name, file);
sfile= curarea->spacedata.first;
/* sfile wants a (*)(short), but get (*)(char*) */
sfile->returnfunc= func;
sfile->type= type;
sfile->ofs= 0;
/* sfile->act wordt gebruikt bij databrowse: dubbele namen van library objecten */
sfile->act= -1;
if(BLI_convertstringcode(name, G.sce, G.scene->r.cfra)) sfile->flag |= FILE_STRINGCODE;
else sfile->flag &= ~FILE_STRINGCODE;
if(type==FILE_MAIN) {
char *groupname;
strcpy(sfile->file, name+2);
groupname = BLO_idcode_to_name( GS(name) );
if (groupname) {
strcpy(sfile->dir, groupname);
strcat(sfile->dir, "/");
}
/* alles vrijgeven */
if(sfile->libfiledata) BLO_blendhandle_close(sfile->libfiledata);
sfile->libfiledata= 0;
freefilelist(sfile);
}
else if(type==FILE_LOADLIB) {
strcpy(sfile->dir, name);
if( is_a_library(sfile, temp, group) ) {
/* dit geval is om een reload van library-filelist te veroorzaken */
if(sfile->libfiledata==0) {
freefilelist(sfile);
}
}
else {
split_sfile(sfile, name);
if(sfile->libfiledata) BLO_blendhandle_close(sfile->libfiledata);
sfile->libfiledata= 0;
}
}
else { /* FILE_BLENDER */
split_sfile(sfile, name); /* test ook de filelist */
/* vrijgeven: filelist en libfiledata kloppen niet meer */
if(sfile->libfiledata) BLO_blendhandle_close(sfile->libfiledata);
sfile->libfiledata= 0;
}
BLI_strncpy(sfile->title, title, sizeof(sfile->title));
filetoname= 1;
}
void activate_imageselect(int type, char *title, char *file, void (*func)(char *))
{
SpaceImaSel *simasel;
char dir[FILE_MAXDIR], name[FILE_MAXFILE];
if(curarea==0) return;
if(curarea->win==0) return;
newspace(curarea, SPACE_IMASEL);
/* is misschien dubbelop, voor geval area al SPACE_FILE is met andere filename */
addqueue(curarea->headwin, CHANGED, 1);
addqueue(curarea->win, CHANGED, 1);
name[2]= 0;
strcpy(name, file);
simasel= curarea->spacedata.first;
simasel->returnfunc= func;
if(BLI_convertstringcode(name, G.sce, G.scene->r.cfra)) simasel->mode |= IMS_STRINGCODE;
else simasel->mode &= ~IMS_STRINGCODE;
BLI_split_dirfile(name, dir, simasel->file);
if(strcmp(dir, simasel->dir)!=0) simasel->fase= 0;
strcpy(simasel->dir, dir);
BLI_strncpy(simasel->title, title, sizeof(simasel->title));
/* filetoname= 1; */
}
void activate_databrowse(ID *id, int idcode, int fromcode, int retval, short *menup, void (*func)(unsigned short))
{
ListBase *lb;
SpaceFile *sfile;
char str[32];
if(id==0) {
lb= wich_libbase(G.main, idcode);
id= lb->first;
}
if(id) strcpy(str, id->name);
else return;
activate_fileselect(FILE_MAIN, "SELECT DATABLOCK", str, (void (*) (char*))func);
sfile= curarea->spacedata.first;
sfile->retval= retval;
sfile->ipotype= fromcode;
sfile->menup= menup;
}
void filesel_prevspace()
{
SpaceFile *sfile;
sfile= curarea->spacedata.first;
if(sfile->next) {
BLI_remlink(&curarea->spacedata, sfile);
BLI_addtail(&curarea->spacedata, sfile);
sfile= curarea->spacedata.first;
newspace(curarea, sfile->spacetype);
}
else newspace(curarea, SPACE_INFO);
}
static int countselect(SpaceFile *sfile)
{
int a, count=0;
for(a=0; a<sfile->totfile; a++) {
if(sfile->filelist[a].flags & ACTIVE) {
count++;
}
}
return count;
}
static int getotherdir(void)
{
ScrArea *sa;
SpaceFile *sfile=0;
sa= G.curscreen->areabase.first;
while(sa) {
if(sa!=curarea) {
if(sa->spacetype==SPACE_FILE) {
/* al een gevonden */
if(sfile) return 0;
sfile= sa->spacedata.first;
if(sfile->type & FILE_UNIX) {
otherarea= sa;
BLI_make_file_string(G.sce, otherdir, sfile->dir, "");
}
else sfile= 0;
}
}
sa= sa->next;
}
if(sfile) return 1;
return 0;
}
static void reread_other_fs(void)
{
SpaceFile *sfile;
/* oppassen: alleen aanroepen als getotherdir goed is afgelopen */
sfile= otherarea->spacedata.first;
freefilelist(sfile);
scrarea_queue_winredraw(otherarea);
}
void free_filesel_spec(char *dir)
{
/* alle filesels met 'dir' worden vrijgegeven */
bScreen *sc;
sc= G.main->screen.first;
while(sc) {
ScrArea *sa= sc->areabase.first;
while(sa) {
SpaceLink *sl= sa->spacedata.first;
while(sl) {
if(sl->spacetype==SPACE_FILE) {
SpaceFile *sfile= (SpaceFile*) sl;
if (BLI_streq(sfile->dir, dir)) {
freefilelist(sfile);
}
}
sl= sl->next;
}
sa= sa->next;
}
sc= sc->id.next;
}
}
static void filesel_execute(SpaceFile *sfile)
{
struct direntry *files;
char name[FILE_MAXDIR];
int a;
filesel_prevspace();
if(sfile->type==FILE_LOADLIB) {
do_library_append(sfile);
allqueue(REDRAWALL, 1);
}
else if(sfile->returnfunc) {
fsmenu_insert_entry(sfile->dir, 1);
if(sfile->type==FILE_MAIN) {
if (sfile->menup) {
if(sfile->act>=0) {
if(sfile->filelist) {
files= sfile->filelist+sfile->act;
*sfile->menup= files->nr;
}
else *sfile->menup= sfile->act+1;
}
else {
*sfile->menup= -1;
for(a=0; a<sfile->totfile; a++) {
if( strcmp(sfile->filelist[a].relname, sfile->file)==0) {
*sfile->menup= a+1;
break;
}
}
}
}
sfile->returnfunc((char*) sfile->retval);
}
else {
if(strncmp(sfile->title, "SAVE", 4)==0) free_filesel_spec(sfile->dir);
strcpy(name, sfile->dir);
strcat(name, sfile->file);
if(sfile->flag & FILE_STRINGCODE) BLI_makestringcode(G.sce, name);
sfile->returnfunc(name);
}
}
}
static void do_filesel_buttons(short event, SpaceFile *sfile)
{
char butname[FILE_MAXDIR];
if (event == 1) {
if (strchr(sfile->file, '*') || strchr(sfile->file, '?') || strchr(sfile->file, '[')) {
int i, match = FALSE;
for (i = 2; i < sfile->totfile; i++) {
if (fnmatch(sfile->file, sfile->filelist[i].relname, 0) == 0) {
sfile->filelist[i].flags |= ACTIVE;
match = TRUE;
}
}
if (match) strcpy(sfile->file, "");
if(sfile->type==FILE_MAIN) filesel_select_objects(sfile);
scrarea_queue_winredraw(curarea);
}
}
else if(event== 2) {
/* reuse the butname variable */
checkdir(sfile->dir);
BLI_make_file_string(G.sce, butname, sfile->dir, "");
/* strip the trailing slash if its a real dir */
if (strlen(butname)!=1)
butname[strlen(butname)-1]=0;
if(sfile->type & FILE_UNIX) {
if (!BLI_exists(butname)) {
if (okee("Makedir")) {
BLI_recurdir_fileops(butname);
if (!BLI_exists(butname)) parent(sfile);
} else parent(sfile);
}
}
freefilelist(sfile);
sfile->ofs= 0;
scrarea_queue_winredraw(curarea);
}
else if(event== 3) {
char *selected= fsmenu_get_entry(sfile->menu-1);
/* welke string */
if (selected) {
strcpy(sfile->dir, selected);
BLI_make_exist(sfile->dir);
checkdir(sfile->dir);
freefilelist(sfile);
sfile->ofs= 0;
scrarea_queue_winredraw(curarea);
}
sfile->act= -1;
}
else if(event== 4) parent(sfile);
else if(event== 5) {
if(sfile->type) filesel_execute(sfile);
}
else if(event== 6) filesel_prevspace();
}
/****/
typedef void (*ReplaceFP)(ID *oldblock, ID *newblock);
static void change_id_link(void *linkpv, void *newlinkv) {
ID **linkp= (ID**) linkpv;
ID *newlink= newlinkv;
if (*linkp) {
(*linkp)->us--;
}
(*linkp)= newlink;
if (newlink) {
id_us_plus(newlink);
}
}
static void replace_image(ID *oldblock, ID *newblock) {
Image *oldima= (Image*) oldblock;
Image *newima= (Image*) newblock;
bScreen *sc;
Scene *sce;
Tex *tex;
Mesh *me;
for (tex= G.main->tex.first; tex; tex= tex->id.next) {
if (tex->env && tex->env->type == ENV_LOAD && tex->env->ima == oldima)
change_id_link(&tex->env->ima, newima);
if (tex->ima == oldima)
change_id_link(&tex->ima, newima);
}
for (sce= G.main->scene.first; sce; sce= sce->id.next) {
if (sce->ima == oldima)
change_id_link(&sce->ima, newima);
}
for (sc= G.main->screen.first; sc; sc= sc->id.next) {
ScrArea *sa;
for (sa= sc->areabase.first; sa; sa= sa->next) {
SpaceLink *sl;
for (sl= sa->spacedata.first; sl; sl= sl->next) {
if (sl->spacetype == SPACE_VIEW3D) {
View3D *v3d= (View3D*) sl;
BGpic *bgp= v3d->bgpic;
if (bgp && bgp->ima == oldima)
change_id_link(&bgp->ima, newima);
} else if (sl->spacetype == SPACE_IMAGE) {
SpaceImage *sima= (SpaceImage*) sl;
if (sima->image == oldima)
change_id_link(&sima->image, newima);
}
}
}
}
for (me= G.main->mesh.first; me; me= me->id.next) {
TFace *tfaces= me->tface;
if (tfaces) {
int i;
for (i=0; i<me->totface; i++) {
TFace *tf= &tfaces[i];
if (tf->tpage == oldima) {
/* not change_id_link, tpage's aren't owners :(
* see hack below.
*/
tf->tpage= newima;
}
}
}
}
/* Nasty hack, necessary because tpages don't act
* as a user, so there lots of image user count
* munging occurs... this will ensure the image
* really dies.
*/
oldima->id.us= 0;
}
static void replace_material(ID *oldblock, ID *newblock)
{
Material *old= (Material*) oldblock;
Material *new= (Material*) newblock;
Material ***matarar;
ID *id;
Object *ob;
int a;
ob= G.main->object.first;
while(ob) {
if(ob->totcol && ob->id.lib==0) {
matarar= give_matarar(ob);
for(a=1; a<=ob->totcol; a++) {
if(ob->mat[a-1] == old) {
if(old) old->id.us--;
id_us_plus((ID *)new);
ob->mat[a-1]= new;
}
id= ob->data;
if( (*matarar)[a-1] == old && id->lib==0) {
if(old) old->id.us--;
id_us_plus((ID *)new);
(*matarar)[a-1]= new;
}
}
}
ob= ob->id.next;
}
}
static ReplaceFP get_id_replace_function(int idcode) {
switch (idcode) {
case ID_MA:
return &replace_material;
case ID_IM:
return &replace_image;
default:
return NULL;
}
}
static void databrowse_replace(SpaceFile *sfile, int idcode)
{
ReplaceFP replace_func= get_id_replace_function(idcode);
if (!replace_func) {
error("Replacing %s blocks is unsupported", BLO_idcode_to_name(idcode));
} else if (sfile->act==-1) {
error("Select target with leftmouse");
} else {
ID *target= (ID*) sfile->filelist[sfile->act].poin;
if (target) {
char buf[128];
sprintf(buf, "Replace with %s: %s", BLO_idcode_to_name(idcode), target->name+2);
if (okee(buf)) {
int i;
for (i = 0; i <sfile->totfile; i++)
if ((sfile->filelist[i].flags&ACTIVE) && sfile->filelist[i].poin!=target)
replace_func(sfile->filelist[i].poin, target);
}
}
}
freefilelist(sfile);
scrarea_queue_winredraw(curarea);
}
static void fs_fake_users(SpaceFile *sfile)
{
ID *id;
int a;
/* alleen bij F4 DATABROWSE */
if(sfile->returnfunc) return;
for(a=0; a<sfile->totfile; a++) {
if(sfile->filelist[a].flags & ACTIVE) {
id= (ID *)sfile->filelist[a].poin;
if(id) {
if( id->flag & LIB_FAKEUSER) {
id->flag -= LIB_FAKEUSER;
id->us--;
}
else {
id->flag |= LIB_FAKEUSER;
id->us++;
}
}
}
}
freefilelist(sfile);
scrarea_queue_winredraw(curarea);
}
void winqreadfilespace(unsigned short event, short val, char ascii)
{
static int acto=0;
SpaceFile *sfile;
int act, do_draw= 0, i, test, ret = 0;
short qual, mval[2];
char str[FILE_MAXDIR+FILE_MAXFILE+12];
sfile= curarea->spacedata.first;
if(sfile==0) return;
if(sfile->filelist==0) {
/* wel buttons doen */
if(val && event==LEFTMOUSE) {
/* FrontbufferButs(TRUE); */
/* event= DoButtons(); */
/* FrontbufferButs(FALSE); */
/* NIET de headerbuttons! */
/* if(event) do_filesel_buttons(event, sfile); */
}
return;
}
if(curarea->win==0) return;
calc_file_rcts(sfile);
getmouseco_areawin(mval);
/* om hangen te voorkomen */
if(selecting && !(get_mbut() & R_MOUSE)) selecting= 0;
if(val) {
if( event!=RETKEY && event!=PADENTER)
if( uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0;
switch(event) {
case UI_BUT_EVENT:
do_filesel_buttons(val, sfile);
break;
case LEFTMOUSE:
case MIDDLEMOUSE:
if(mval[0]>scrollrct.xmin && mval[0]<scrollrct.xmax && mval[1]>scrollrct.ymin && mval[1]<scrollrct.ymax) {
do_filescroll(sfile);
}
else if(mval[0]>textrct.xmin && mval[0]<textrct.xmax && mval[1]>textrct.ymin && mval[1]<textrct.ymax) {
/* sfile->act wordt gebruikt bij databrowse: dubbelenamen van library objecten */
sfile->act= act= find_active_file(sfile, mval[0], mval[1]);
if(act>=0 && act<sfile->totfile) {
if(S_ISDIR(sfile->filelist[act].type)) {
strcat(sfile->dir, sfile->filelist[act].relname);
strcat(sfile->dir,"/");
checkdir(sfile->dir);
freefilelist(sfile);
sfile->ofs= 0;
do_draw= 1;
}
else {
if( strcmp(sfile->file, sfile->filelist[act].relname)) {
do_draw= 1;
strcpy(sfile->file, sfile->filelist[act].relname);
}
if(event==MIDDLEMOUSE && sfile->type) filesel_execute(sfile);
}
}
}
else {
/* FrontbufferButs(TRUE); */
/* event= DoButtons(); */
/* FrontbufferButs(FALSE); */
/* NIET de headerbuttons! */
/* if(event) do_filesel_buttons(event, sfile); */
}
break;
case RIGHTMOUSE:
act= find_active_file(sfile, mval[0], mval[1]);
acto= act;
if(act>=0 && act<sfile->totfile) {
if (sfile->filelist[act].flags & ACTIVE) {
sfile->filelist[act].flags &= ~ACTIVE;
selecting = INACTIVATE;
}
else {
test= sfile->filelist[act].relname[0];
if (act>=2 || test!='.') sfile->filelist[act].flags |= ACTIVE;
selecting = ACTIVATE;
}
do_draw= 1;
}
break;
case MOUSEY:
act= find_active_file(sfile, mval[0], mval[1]);
if (act!=acto) {
set_active_file(sfile, act);
}
if(selecting && act!=acto) {
while(1) {
if (acto >= 2 && acto < sfile->totfile) {
if (selecting == ACTIVATE) sfile->filelist[acto].flags |= ACTIVE;
else if (selecting == INACTIVATE) sfile->filelist[acto].flags &= ~ACTIVE;
}
if (acto < act) acto++;
else if (acto > act) acto--;
else break;
}
}
acto= act;
break;
case PAGEUPKEY:
sfile->ofs-= page_ofs;
do_draw= 1;
break;
case PAGEDOWNKEY:
sfile->ofs+= page_ofs;
do_draw= 1;
break;
case HOMEKEY:
sfile->ofs= 0;
do_draw= 1;
break;
case ENDKEY:
sfile->ofs= sfile->totfile;
do_draw= 1;
break;
case AKEY:
swapselect_file(sfile);
if(sfile->type==FILE_MAIN) filesel_select_objects(sfile);
do_draw= 1;
break;
case BKEY:
case CKEY:
case LKEY:
if(event==LKEY && sfile->type==FILE_MAIN && (G.qual & LR_CTRLKEY)) {
databrowse_replace(sfile, groupname_to_code(sfile->dir));
break;
}
/* doorgeven */
case MKEY:
if(sfile->type==FILE_MAIN) break;
if(!countselect(sfile)) {
error("No files selected");
break;
}
if(!getotherdir()) {
error("No second fileselect");
break;
}
if (!strcmp(sfile->dir, otherdir)) {
error("Same directories");
break;
}
if(event==BKEY) sprintf(str, "Backup to %s", otherdir);
else if(event==CKEY) sprintf(str, "Copy to %s", otherdir);
else if(event==LKEY) sprintf(str, "Linked copy to %s", otherdir);
else if(event==MKEY) sprintf(str, "Move to %s", otherdir);
if (!okee(str)) break;
for (i = 0; i<sfile->totfile; i++){
if (sfile->filelist[i].flags & ACTIVE) {
BLI_make_file_string(G.sce, str, sfile->dir, sfile->filelist[i].relname);
if(event==BKEY) ret= BLI_backup(sfile->filelist[i].relname, sfile->dir, otherdir);
else if(event==CKEY) ret= BLI_copy_fileops(str, otherdir);
else if(event==LKEY) ret= BLI_link(str, otherdir);
else if(event==MKEY) ret= BLI_move(str, otherdir);
if (ret) {error("Command failed, see console"); break;}
else sfile->filelist[i].flags &= ~ACTIVE;
}
}
do_draw= 1;
if(event==BKEY || event==MKEY)
freefilelist(sfile);
reread_other_fs();
break;
case RKEY:
if(sfile->type==FILE_MAIN) {
databrowse_replace(sfile, groupname_to_code(sfile->dir));
break;
}
/* doorgeven aan TKEY! */
case TKEY:
if(sfile->type==FILE_MAIN) break;
if(!countselect(sfile)) {
error("No files selected");
break;
}
if(event==TKEY) sprintf(str, "Touch");
else if(event==RKEY) sprintf(str, "Remove from %s", sfile->dir);
qual= G.qual; /* want na okee() heb je de shift losgelaten */
if (!okee(str)) break;
for (i = 0; i <sfile->totfile; i++) {
if (sfile->filelist[i].flags & ACTIVE) {
BLI_make_file_string(G.sce, str, sfile->dir, sfile->filelist[i].relname);
if(event==TKEY) ret= BLI_touch(str);
else if(event==RKEY) {
if(qual & LR_SHIFTKEY) ret= BLI_delete(str, 0, 1);
else if(S_ISDIR(sfile->filelist[i].type)) ret= BLI_delete(str, 1, 0);
else ret= BLI_delete(str, 0, 0);
}
if (ret) {error("Command failed, see console"); break;}
else sfile->filelist[i].flags &= ~ACTIVE;
}
}
do_draw= 1;
freefilelist(sfile);
break;
case PKEY:
if(G.qual & LR_SHIFTKEY) {
extern char bprogname[]; /* usiblender.c */
sprintf(str, "%s -a \"%s%s\"", bprogname, sfile->dir, sfile->file);
system(str);
}
else
parent(sfile);
break;
case IKEY:
if(sfile->type==FILE_MAIN) break;
sprintf(str, "$IMAGEEDITOR %s%s", sfile->dir, sfile->file);
system(str);
break;
case EKEY:
if(sfile->type==FILE_MAIN) break;
sprintf(str, "$WINEDITOR %s%s", sfile->dir, sfile->file);
system(str);
break;
case FKEY:
if(sfile->type==FILE_MAIN) {
fs_fake_users(sfile);
}
break;
case PADPLUSKEY:
case EQUALKEY:
if (G.qual & LR_CTRLKEY) BLI_newname(sfile->file, +100);
else if (G.qual & LR_SHIFTKEY) BLI_newname(sfile->file, +10);
else BLI_newname(sfile->file, +1);
do_draw= 1;
break;
case PADMINUS:
case MINUSKEY:
if (G.qual & LR_CTRLKEY) BLI_newname(sfile->file, -100);
else if (G.qual & LR_SHIFTKEY) BLI_newname(sfile->file, -10);
else BLI_newname(sfile->file, -1);
do_draw= 1;
break;
case BACKSLASHKEY:
case SLASHKEY:
if(sfile->type==FILE_MAIN) break;
#ifdef WIN32
strcpy(sfile->dir, "\\");
#else
strcpy(sfile->dir, "/");
#endif
freefilelist(sfile);
sfile->ofs= 0;
do_draw= 1;
break;
case PERIODKEY:
freefilelist(sfile);
do_draw= 1;
break;
case ESCKEY:
filesel_prevspace();
break;
case PADENTER:
case RETKEY:
if(sfile->type) filesel_execute(sfile);
break;
}
}
else if(event==RIGHTMOUSE) {
selecting = NOTACTIVE;
if(sfile->type==FILE_MAIN) filesel_select_objects(sfile);
}
else if(event==LEFTMOUSE) {
if(sfile->type==FILE_MAIN) active_file_object(sfile);
}
/* XXX, stupid patch, curarea can become undone
* because of file loading... fixme zr
*/
if(do_draw && curarea) scrarea_queue_winredraw(curarea);
}
/* ************* LIBRARY FILESEL ******************* */
static int groupname_to_code(char *group)
{
char buf[32];
char *lslash;
strcpy(buf, group);
lslash= BLI_last_slash(buf);
if (lslash)
lslash[0]= '\0';
return BLO_idcode_from_name(buf);
}
static int is_a_library(SpaceFile *sfile, char *dir, char *group)
{
/* return ok als een blenderfile, in dir staat de filename,
* in group het type libdata
*/
int len;
char *fd;
strcpy(dir, sfile->dir);
len= strlen(dir);
if(len<7) return 0;
if( dir[len-1] != '/' && dir[len-1] != '\\') return 0;
group[0]= 0;
dir[len-1]= 0;
/* Find the last slash */
fd= (strrchr(dir, '/')>strrchr(dir, '\\'))?strrchr(dir, '/'):strrchr(dir, '\\');
if(fd==0) return 0;
*fd= 0;
if(BLO_has_bfile_extension(fd+1)) {
*fd= '/';
}
else {
strcpy(group, fd+1);
/* Find the last slash */
fd= (strrchr(dir, '/')>strrchr(dir, '\\'))?strrchr(dir, '/'):strrchr(dir, '\\');
if (!fd || !BLO_has_bfile_extension(fd+1)) return 0;
}
return 1;
}
static void do_library_append(SpaceFile *sfile)
{
char dir[FILE_MAXDIR], group[32];
if ( is_a_library(sfile, dir, group)==0 ) {
error("Not a library");
} else if (!sfile->libfiledata) {
error("Library not loaded");
} else if (group[0]==0) {
error("Nothing indicated");
} else if (BLI_streq(G.main->name, dir)) {
error("Cannot use current file as library");
} else {
Object *ob;
int idcode = groupname_to_code(group);
BLO_library_append(sfile, dir, idcode);
/* DISPLISTEN */
ob= G.main->object.first;
set_displist_onlyzero(1);
while(ob) {
if(ob->id.lib) {
if(ob->type==OB_FONT) {
Curve *cu= ob->data;
if(cu->nurb.first==0) text_to_curve(ob, 0);
}
makeDispList(ob);
}
else if(ob->type==OB_MESH && ob->parent && ob->parent->type==OB_LATTICE ) {
makeDispList(ob);
}
ob= ob->id.next;
}
set_displist_onlyzero(0);
/* in sfile->dir staat de HELE libnaam */
strcpy(G.lib, sfile->dir);
if((sfile->flag & FILE_LINK)==0) all_local();
}
}
static void library_to_filelist(SpaceFile *sfile)
{
char dir[FILE_MAXDIR], group[24];
int ok, i, nnames, idcode;
LinkNode *l, *names;
/* name testen */
ok= is_a_library(sfile, dir, group);
if (!ok) {
/* vrijgeven */
if(sfile->libfiledata) BLO_blendhandle_close(sfile->libfiledata);
sfile->libfiledata= 0;
return;
}
/* en daar gaat ie */
/* voorlopig alleen filedata inlezen als libfiledata==0 */
if (sfile->libfiledata==0) {
sfile->libfiledata= BLO_blendhandle_from_file(dir);
if(sfile->libfiledata==0) return;
}
if (idcode= groupname_to_code(group)) {
names= BLO_blendhandle_get_datablock_names(sfile->libfiledata, idcode);
} else {
names= BLO_blendhandle_get_linkable_groups(sfile->libfiledata);
}
nnames= BLI_linklist_length(names);
sfile->totfile= nnames + 2;
sfile->filelist= malloc(sfile->totfile * sizeof(*sfile->filelist));
memset(sfile->filelist, 0, sfile->totfile * sizeof(*sfile->filelist));
sfile->filelist[0].relname= strdup(".");
sfile->filelist[0].type |= S_IFDIR;
sfile->filelist[1].relname= strdup("..");
sfile->filelist[1].type |= S_IFDIR;
for (i=0, l= names; i<nnames; i++, l= l->next) {
char *blockname= l->link;
sfile->filelist[i + 2].relname= blockname;
if (!idcode)
sfile->filelist[i + 2].type |= S_IFDIR;
}
BLI_linklist_free(names, NULL);
qsort(sfile->filelist, sfile->totfile, sizeof(struct direntry), compare_name);
sfile->maxnamelen= 0;
for(i=0; i<sfile->totfile; i++) {
int len = BMF_GetStringWidth(G.font, sfile->filelist[i].relname);
if (len > sfile->maxnamelen)
sfile->maxnamelen = len;
}
}
/* ******************* DATA SELECT ********************* */
static void filesel_select_objects(SpaceFile *sfile)
{
Object *ob;
Base *base;
Scene *sce;
int a;
/* alleen bij F4 DATABROWSE */
if(sfile->returnfunc) return;
if( strcmp(sfile->dir, "Object/")==0 ) {
for(a=0; a<sfile->totfile; a++) {
ob= (Object *)sfile->filelist[a].poin;
if(ob) {
if(sfile->filelist[a].flags & ACTIVE) ob->flag |= SELECT;
else ob->flag &= ~SELECT;
}
}
base= FIRSTBASE;
while(base) {
base->flag= base->object->flag;
base= base->next;
}
allqueue(REDRAWVIEW3D, 0);
}
else if( strcmp(sfile->dir, "Scene/")==0 ) {
for(a=0; a<sfile->totfile; a++) {
sce= (Scene *)sfile->filelist[a].poin;
if(sce) {
if(sfile->filelist[a].flags & ACTIVE) sce->r.scemode |= R_BG_RENDER;
else sce->r.scemode &= ~R_BG_RENDER;
}
}
allqueue(REDRAWBUTSRENDER, 0);
}
}
static void active_file_object(SpaceFile *sfile)
{
Object *ob;
/* alleen bij F4 DATABROWSE */
if(sfile->returnfunc) return;
if( strcmp(sfile->dir, "Object/")==0 ) {
if(sfile->act >= 0) {
ob= (Object *)sfile->filelist[sfile->act].poin;
if(ob) {
set_active_object(ob);
if(BASACT && BASACT->object==ob) {
BASACT->flag |= SELECT;
sfile->filelist[sfile->act].flags |= ACTIVE;
allqueue(REDRAWVIEW3D, 0);
scrarea_queue_winredraw(curarea);
}
}
}
}
}
void main_to_filelist(SpaceFile *sfile)
{
ID *id;
struct direntry *files, *firstlib = NULL;
ListBase *lb;
int a, fake, idcode, len, ok, totlib, totbl;
if(sfile->dir[0]=='/') sfile->dir[0]= 0;
if(sfile->dir[0]) {
idcode= groupname_to_code(sfile->dir);
if(idcode==0) sfile->dir[0]= 0;
}
if( sfile->dir[0]==0) {
/* directories maken */
sfile->totfile= 22;
sfile->filelist= (struct direntry *)malloc(sfile->totfile * sizeof(struct direntry));
for(a=0; a<sfile->totfile; a++) {
memset( &(sfile->filelist[a]), 0 , sizeof(struct direntry));
sfile->filelist[a].type |= S_IFDIR;
}
sfile->filelist[0].relname= strdup("..");
sfile->filelist[1].relname= strdup(".");
sfile->filelist[2].relname= strdup("Scene");
sfile->filelist[3].relname= strdup("Object");
sfile->filelist[4].relname= strdup("Mesh");
sfile->filelist[5].relname= strdup("Curve");
sfile->filelist[6].relname= strdup("Metaball");
sfile->filelist[7].relname= strdup("Material");
sfile->filelist[8].relname= strdup("Texture");
sfile->filelist[9].relname= strdup("Image");
sfile->filelist[10].relname= strdup("Ika");
sfile->filelist[11].relname= strdup("Wave");
sfile->filelist[12].relname= strdup("Lattice");
sfile->filelist[13].relname= strdup("Lamp");
sfile->filelist[14].relname= strdup("Camera");
sfile->filelist[15].relname= strdup("Ipo");
sfile->filelist[16].relname= strdup("World");
sfile->filelist[17].relname= strdup("Screen");
sfile->filelist[18].relname= strdup("VFont");
sfile->filelist[19].relname= strdup("Text");
sfile->filelist[20].relname= strdup("Armature");
sfile->filelist[21].relname= strdup("Action");
qsort(sfile->filelist, sfile->totfile, sizeof(struct direntry), compare_name);
}
else {
/* files maken */
idcode= groupname_to_code(sfile->dir);
lb= wich_libbase(G.main, idcode );
if(lb==0) return;
id= lb->first;
sfile->totfile= 0;
while(id) {
if(sfile->returnfunc && idcode==ID_IP) {
if(sfile->ipotype== ((Ipo *)id)->blocktype) sfile->totfile++;
}
else sfile->totfile++;
id= id->next;
}
if(sfile->returnfunc==0) sfile->totfile+= 2;
sfile->filelist= (struct direntry *)malloc(sfile->totfile * sizeof(struct direntry));
files= sfile->filelist;
if(sfile->returnfunc==0) {
memset( &(sfile->filelist[0]), 0 , sizeof(struct direntry));
sfile->filelist[0].relname= strdup(".");
sfile->filelist[0].type |= S_IFDIR;
memset( &(sfile->filelist[1]), 0 , sizeof(struct direntry));
sfile->filelist[1].relname= strdup("..");
sfile->filelist[1].type |= S_IFDIR;
files+= 2;
}
id= lb->first;
totlib= totbl= 0;
while(id) {
ok= 0;
if(sfile->returnfunc && idcode==ID_IP) {
if(sfile->ipotype== ((Ipo *)id)->blocktype) ok= 1;
}
else ok= 1;
if(ok) {
memset( files, 0 , sizeof(struct direntry));
files->relname= strdup(id->name+2);
if(sfile->returnfunc==0) { /* F4 DATA BROWSE */
if(idcode==ID_OB) {
if( ((Object *)id)->flag & SELECT) files->flags |= ACTIVE;
}
else if(idcode==ID_SCE) {
if( ((Scene *)id)->r.scemode & R_BG_RENDER) files->flags |= ACTIVE;
}
}
files->nr= totbl+1;
files->poin= id;
fake= id->flag & LIB_FAKEUSER;
if(id->lib && fake) sprintf(files->extra, "LF %d", id->us);
else if(id->lib) sprintf(files->extra, "L %d", id->us);
else if(fake) sprintf(files->extra, "F %d", id->us);
else sprintf(files->extra, " %d", id->us);
if(id->lib) {
if(totlib==0) firstlib= files;
totlib++;
}
files++;
totbl++;
}
id= id->next;
}
/* alleen qsort van libraryblokken */
if(totlib>1) {
qsort(firstlib, totlib, sizeof(struct direntry), compare_name);
}
}
sfile->maxnamelen= 0;
for(a=0; a<sfile->totfile; a++) {
len = BMF_GetStringWidth(G.font, sfile->filelist[a].relname);
if (len > sfile->maxnamelen) sfile->maxnamelen = len;
if(filetoname) {
if( strcmp(sfile->file, sfile->filelist[a].relname)==0) {
sfile->ofs= a-( sfile->collums*(curarea->winy-FILESELHEAD-10)/(2*FILESEL_DY));
filetoname= 0;
if(sfile->returnfunc) sfile->filelist[a].flags |= ACTIVE;
}
}
}
}