56 # include <Carbon/Carbon.h>
129 const char *xdg_config_home = getenv(
"XDG_CONFIG_HOME");
130 if (xdg_config_home !=
NULL) {
131 BLI_path_join(filepath,
sizeof(filepath), xdg_config_home,
"user-dirs.dirs",
NULL);
134 BLI_path_join(filepath,
sizeof(filepath), home,
".config",
"user-dirs.dirs",
NULL);
143 while (fgets(
l,
sizeof(
l), fp) !=
NULL) {
147 char *l_value = strchr(
l,
'=');
148 if (l_value !=
NULL) {
153 const uint l_value_len = strlen(l_value);
154 if ((l_value[0] ==
'"') && (l_value_len > 0) && (l_value[l_value_len - 1] ==
'"')) {
155 l_value[l_value_len - 1] =
'\0';
159 char *l_value_final = l_value;
165 BLI_path_join(l_value_expanded,
sizeof(l_value_expanded), home, l_value + 6,
NULL);
166 l_value_final = l_value_expanded;
181 if (xdg_map !=
NULL) {
197 const char *default_path,
203 if (xdg_path ==
NULL) {
205 xdg_path = xdg_path_buf;
251 fsm_iter = fsm_iter->
next) {
260 return fsentry->
path;
282 return (fsentry->
icon) ? fsentry->
icon : ICON_FILE_FOLDER;
309 if (fsentry->
name[0]) {
310 return fsentry->
name;
315 size_t name_size =
sizeof(fsentry->
name) - 1;
325 size_t tmp_name_size =
sizeof(tmp_name);
330 fsentry->
name[0] =
'\0';
346 if (fsentry->
path && fsentry->
path[0]) {
351 const char *exceptions[] = {
"A:\\",
"B:\\",
NULL};
352 const size_t exceptions_len[] = {strlen(exceptions[0]), strlen(exceptions[1]), 0};
355 for (i = 0; exceptions[i]; i++) {
357 fsentry->
valid =
true;
365 fsentry->
valid =
false;
374 fsm_iter = fsm_iter->
next) {
378 return fsm_iter ? fsm_iter->
save : 0;
393 const bool has_trailing_slash = (
path[path_len - 1] ==
SEP);
401 for (fsm_iter = fsm_head; fsm_iter; fsm_prev = fsm_iter, fsm_iter = fsm_iter->
next) {
402 if (fsm_iter->
path) {
405 if (cmp_ret == 0 &&
STREQ(fsm_iter->
path + path_len, has_trailing_slash ?
"" :
SEP_STR)) {
407 if (fsm_iter != fsm_head) {
409 fsm_iter->
next = fsm_head;
430 if (has_trailing_slash) {
435 fsm_iter->
path[path_len] =
SEP;
436 fsm_iter->
path[path_len + 1] =
'\0';
457 for (; tfsm; tfsm = tfsm->
next) {
476 fsm_iter->
name[0] =
'\0';
485 fsm_iter->
next = fsm_head;
490 fsm_prev->
next = fsm_iter;
494 fsm_iter->
next = fsm_head;
507 for (fsm_iter = fsm_head; fsm_iter && idx; fsm_prev = fsm_iter, fsm_iter = fsm_iter->
next) {
515 if (fsm_iter->
save && fsm_iter->
path) {
522 fsm_head = fsm_iter->
next;
543 fprintf(fp,
"[Bookmarks]\n");
545 fsm_iter = fsm_iter->
next) {
546 if (fsm_iter->
path && fsm_iter->
save) {
549 fprintf(fp,
"!%s\n", fsm_iter->
name);
551 fprintf(fp,
"%s\n", fsm_iter->
path);
554 fprintf(fp,
"[Recent]\n");
557 fsm_iter = fsm_iter->
next, nwritten++) {
558 if (fsm_iter->
path && fsm_iter->
save) {
561 fprintf(fp,
"!%s\n", fsm_iter->
name);
563 fprintf(fp,
"%s\n", fsm_iter->
path);
583 while (fgets(line,
sizeof(line), fp) !=
NULL) {
590 else if (line[0] ==
'!') {
591 int len = strlen(line);
593 if (line[
len - 1] ==
'\n') {
594 line[
len - 1] =
'\0';
600 int len = strlen(line);
602 if (line[
len - 1] ==
'\n') {
603 line[
len - 1] =
'\0';
624 static void fsmenu_add_windows_folder(
struct FSMenu *fsmenu,
626 REFKNOWNFOLDERID rfid,
633 if (SHGetKnownFolderPath(rfid, 0,
NULL, &pPath) == S_OK) {
635 CoTaskMemFree(pPath);
651 tmp = GetLogicalDrives();
653 for (
int i = 0; i < 26; i++) {
654 if ((tmp >> i) & 1) {
664 SHFILEINFOW shFile = {0};
666 if (SHGetFileInfoW(wline, 0, &shFile,
sizeof(SHFILEINFOW), SHGFI_DISPLAYNAME)) {
675 int icon = ICON_DISK_DRIVE;
676 switch (GetDriveType(tmps)) {
677 case DRIVE_REMOVABLE:
678 icon = ICON_EXTERNAL_DRIVE;
685 icon = ICON_DISK_DRIVE;
688 icon = ICON_NETWORK_DRIVE;
697 if (read_bookmarks) {
700 fsmenu_add_windows_folder(fsmenu,
706 fsmenu_add_windows_folder(fsmenu,
712 fsmenu_add_windows_folder(fsmenu,
718 fsmenu_add_windows_folder(fsmenu,
724 fsmenu_add_windows_folder(fsmenu,
730 fsmenu_add_windows_folder(fsmenu,
736 fsmenu_add_windows_folder(fsmenu,
742 fsmenu_add_windows_folder(fsmenu,
751 fsmenu_add_windows_folder(
754 fsmenu_add_windows_folder(
758 #elif defined(__APPLE__)
773 # define FS_MACOS_PATH(path, name, icon) \
774 BLI_snprintf(line, sizeof(line), path, home); \
775 fsmenu_insert_entry(fsmenu, FS_CATEGORY_OTHER, line, name, icon, FS_INSERT_LAST);
777 FS_MACOS_PATH(
"%s/",
NULL, ICON_HOME)
778 FS_MACOS_PATH(
"%s/Desktop/",
N_(
"Desktop"), ICON_DESKTOP)
779 FS_MACOS_PATH(
"%s/Documents/",
N_(
"Documents"), ICON_DOCUMENTS)
780 FS_MACOS_PATH(
"%s/Downloads/",
N_(
"Downloads"), ICON_IMPORT)
781 FS_MACOS_PATH(
"%s/Movies/",
N_(
"Movies"), ICON_FILE_MOVIE)
782 FS_MACOS_PATH(
"%s/Music/",
N_(
"Music"), ICON_FILE_SOUND)
783 FS_MACOS_PATH(
"%s/Pictures/",
N_(
"Pictures"), ICON_FILE_IMAGE)
784 FS_MACOS_PATH(
"%s/Library/Fonts/",
N_(
"Fonts"), ICON_FILE_FONT)
786 # undef FS_MACOS_PATH
795 CFURLRef cfURL =
NULL;
796 CFURLEnumeratorResult
result = kCFURLEnumeratorSuccess;
797 CFURLEnumeratorRef volEnum = CFURLEnumeratorCreateForMountedVolumes(
798 NULL, kCFURLEnumeratorSkipInvisibles,
NULL);
800 while (
result != kCFURLEnumeratorEnd) {
803 result = CFURLEnumeratorGetNextURL(volEnum, &cfURL,
NULL);
804 if (
result != kCFURLEnumeratorSuccess) {
808 CFURLGetFileSystemRepresentation(cfURL,
false, (UInt8 *)defPath,
FILE_MAX);
812 CFStringRef nameString =
NULL;
813 CFURLCopyResourcePropertyForKey(cfURL, kCFURLVolumeLocalizedNameKey, &nameString,
NULL);
814 if (nameString !=
NULL) {
815 CFStringGetCString(nameString,
name,
sizeof(
name), kCFStringEncodingUTF8);
816 CFRelease(nameString);
820 int icon = ICON_DISK_DRIVE;
821 CFBooleanRef localKey =
NULL;
822 CFURLCopyResourcePropertyForKey(cfURL, kCFURLVolumeIsLocalKey, &localKey,
NULL);
823 if (localKey !=
NULL) {
824 if (!CFBooleanGetValue(localKey)) {
825 icon = ICON_NETWORK_DRIVE;
828 CFBooleanRef ejectableKey =
NULL;
829 CFURLCopyResourcePropertyForKey(cfURL, kCFURLVolumeIsEjectableKey, &ejectableKey,
NULL);
830 if (ejectableKey !=
NULL) {
831 if (CFBooleanGetValue(ejectableKey)) {
832 icon = ICON_EXTERNAL_DRIVE;
834 CFRelease(ejectableKey);
848 # pragma GCC diagnostic push
849 # pragma GCC diagnostic ignored "-Wdeprecated-declarations"
851 if (read_bookmarks) {
853 LSSharedFileListRef list = LSSharedFileListCreate(
854 NULL, kLSSharedFileListFavoriteItems,
NULL);
855 CFArrayRef pathesArray = LSSharedFileListCopySnapshot(list, &
seed);
856 CFIndex pathesCount = CFArrayGetCount(pathesArray);
858 for (CFIndex i = 0; i < pathesCount; i++) {
859 LSSharedFileListItemRef itemRef = (LSSharedFileListItemRef)CFArrayGetValueAtIndex(
862 CFURLRef cfURL =
NULL;
863 OSErr
err = LSSharedFileListItemResolve(itemRef,
864 kLSSharedFileListNoUserInteraction |
865 kLSSharedFileListDoNotMountVolumes,
868 if (
err != noErr || !cfURL) {
872 CFStringRef pathString = CFURLCopyFileSystemPath(cfURL, kCFURLPOSIXPathStyle);
874 if (pathString ==
NULL ||
875 !CFStringGetCString(pathString, line,
sizeof(line), kCFStringEncodingUTF8)) {
881 if (!strstr(line,
"myDocuments.cannedSearch") && (*line !=
'\0')) {
886 CFRelease(pathString);
890 CFRelease(pathesArray);
893 # pragma GCC diagnostic pop
900 if (read_bookmarks && home) {
910 const char *default_path;
913 {
"XDG_DESKTOP_DIR",
"Desktop", ICON_DESKTOP},
914 {
"XDG_DOCUMENTS_DIR",
"Documents", ICON_DOCUMENTS},
915 {
"XDG_DOWNLOAD_DIR",
"Downloads", ICON_IMPORT},
916 {
"XDG_VIDEOS_DIR",
"Videos", ICON_FILE_MOVIE},
917 {
"XDG_PICTURES_DIR",
"Pictures", ICON_FILE_IMAGE},
918 {
"XDG_MUSIC_DIR",
"Music", ICON_FILE_SOUND},
921 for (
int i = 0; i <
ARRAY_SIZE(xdg_items); i++) {
923 xdg_map, fsmenu, xdg_items[i].key, xdg_items[i].default_path, xdg_items[i].icon, home);
936 fp = setmntent(MOUNTED,
"r");
938 fprintf(stderr,
"could not get a list of mounted file-systems\n");
941 while ((mnt = getmntent(fp))) {
946 if (!
STRPREFIX(mnt->mnt_fsname,
"/dev")) {
949 if (
STRPREFIX(mnt->mnt_fsname,
"/dev/loop")) {
960 if (endmntent(fp) == 0) {
961 fprintf(stderr,
"could not close the list of mounted filesystems\n");
965 const char *
const xdg_runtime_dir =
BLI_getenv(
"XDG_RUNTIME_DIR");
966 if (xdg_runtime_dir !=
NULL) {
971 for (
uint i = 0; i < dir_len; i++) {
972 if ((dir[i].
type & S_IFDIR)) {
981 const char *label_test =
label + 6;
1004 #if defined(WIN32) || defined(__APPLE__)
1012 #define FS_UDIR_PATH(dir, icon) \
1013 if (BLI_strnlen(dir, 3) > 2) { \
1014 fsmenu_insert_entry(fsmenu, FS_CATEGORY_OTHER, dir, NULL, icon, FS_INSERT_LAST); \
1033 if (fsm_iter->
path) {
1038 fsm_iter = fsm_next;
1056 if (*fsmenu !=
NULL) {
1074 struct FSMenu *fsmenu_src,
1080 for (; fsm_src_iter !=
NULL; fsm_src_iter = fsm_src_iter->
next) {
1086 if (fsm_dst_prev !=
NULL) {
1087 fsm_dst_prev->
next = fsm_dst;
1090 fsm_dst_head = fsm_dst;
1092 fsm_dst_prev = fsm_dst;
1116 for (i = 0; fsm_iter; fsm_iter = fsm_iter->
next, i++) {
1137 FSMenu *fsmenu = fsmenuv;
1139 int categories[] = {
1142 for (
size_t i =
ARRAY_SIZE(categories); i--;) {
1144 for (; fsm_iter; fsm_iter = fsm_iter->
next) {
1158 FSMenu *fsmenu_job = fsmenuv;
1160 int categories[] = {
1163 for (
size_t i =
ARRAY_SIZE(categories); i--;) {
1166 for (; fsm_iter_dst !=
NULL; fsm_iter_dst = fsm_iter_dst->
next) {
1167 while (fsm_iter_src !=
NULL && !
STREQ(fsm_iter_dst->
path, fsm_iter_src->
path)) {
1168 fsm_iter_src = fsm_iter_src->
next;
1170 if (fsm_iter_src ==
NULL) {
1186 FSMenu *fsmenu = fsmenuv;
const char * BKE_appdir_folder_id_create(const int folder_id, const char *subfolder)
#define BLENDER_BOOKMARK_FILE
int BLI_exists(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
void BLI_filelist_free(struct direntry *filelist, const unsigned int nrentries)
unsigned int BLI_filelist_dir_contents(const char *dir, struct direntry **r_filelist)
bool BLI_is_dir(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
FILE * BLI_fopen(const char *filename, const char *mode) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Some types for dealing with directories.
GHash * BLI_ghash_str_new_ex(const char *info, const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void BLI_ghash_insert(GHash *gh, void *key, void *val)
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
void * BLI_ghash_lookup(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
void BLI_join_dirfile(char *__restrict dst, const size_t maxlen, const char *__restrict dir, const char *__restrict file) ATTR_NONNULL()
size_t BLI_path_join(char *__restrict dst, const size_t dst_len, const char *path_first,...) ATTR_NONNULL(1
const char * BLI_getenv(const char *env) ATTR_NONNULL(1)
bool BLI_path_name_at_index(const char *__restrict path, const int index, int *__restrict r_offset, int *__restrict r_len) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT
void BLI_str_rstrip(char *str) ATTR_NONNULL()
char * BLI_strdupn(const char *str, const size_t len) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
size_t BLI_strncpy_wchar_as_utf8(char *__restrict dst, const wchar_t *__restrict src, const size_t maxncpy) ATTR_NONNULL()
size_t BLI_strncpy_wchar_from_utf8(wchar_t *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
#define UNUSED_VARS_NDEBUG(...)
#define STRCASEEQLEN(a, b, n)
Compatibility-like things for windows.
const char * dirname(char *path)
@ FS_CATEGORY_SYSTEM_BOOKMARKS
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
Read Guarded memory(de)allocation.
@ WM_JOB_TYPE_FSMENU_BOOKMARK_VALIDATE
#define ND_SPACE_FILE_LIST
ATTR_WARN_UNUSED_RESULT const BMLoop * l
static unsigned long seed
void(* MEM_freeN)(void *vmemh)
void *(* MEM_dupallocN)(const void *vmemh)
void *(* MEM_callocN)(size_t len, const char *str)
void *(* MEM_mallocN)(size_t len, const char *str)
struct wmWindow * winactive
void WM_jobs_start(wmWindowManager *wm, wmJob *wm_job)
wmJob * WM_jobs_get(wmWindowManager *wm, wmWindow *win, void *owner, const char *name, int flag, int job_type)
void WM_jobs_callbacks(wmJob *wm_job, wm_jobs_start_callback startjob, void(*initjob)(void *), void(*update)(void *), void(*endjob)(void *))
void WM_jobs_kill_type(struct wmWindowManager *wm, void *owner, int job_type)
void WM_jobs_customdata_set(wmJob *wm_job, void *customdata, void(*free)(void *))
void WM_jobs_timer(wmJob *wm_job, double timestep, unsigned int note, unsigned int endnote)