diff options
Diffstat (limited to 'src/os_mac.c')
-rw-r--r-- | src/os_mac.c | 1451 |
1 files changed, 1451 insertions, 0 deletions
diff --git a/src/os_mac.c b/src/os_mac.c new file mode 100644 index 000000000..0f6a76ceb --- /dev/null +++ b/src/os_mac.c @@ -0,0 +1,1451 @@ +/* vi:set ts=8 sts=4 sw=4: + * + * VIM - Vi IMproved by Bram Moolenaar + * + * Do ":help uganda" in Vim to read copying and usage conditions. + * Do ":help credits" in Vim to see a list of people who contributed. + * See README.txt for an overview of the Vim source code. + */ + +/* + * os_mac.c -- code for the MacOS + * + * This file is mainly based on os_unix.c. + */ + +#include "vim.h" + +#if defined(__MRC__) || defined(__SC__) /* for Apple MPW Compilers */ + +#include "StandardFile.h" + +/* + * Implements the corresponding unix function + */ + int +stat( + char *p, + struct stat *p_st) +{ + /* + TODO: Use functions which fill the FileParam struct (Files.h) + and copy these contents to our self-defined stat struct + */ + return 0; +} +#endif + +/* + * change the current working directory + */ + int +mch_chdir(char *p_name) +{ +#if defined(__MRC__) || defined(__SC__) /* for Apple MPW Compilers */ + /* TODO */ + return FAIL; +#else + return chdir(p_name); +#endif +} + + +/* + * Recursively build up a list of files in "gap" matching the first wildcard + * in `path'. Called by mch_expandpath(). + * "path" has backslashes before chars that are not to be expanded. + */ + int +mac_expandpath( + garray_T *gap, + char_u *path, + int flags, /* EW_* flags */ + short start_at, + short as_full) +{ + /* + * TODO: + * +Get Volumes (when looking for files in current dir) + * +Make it work when working dir not on select volume + * +Cleanup + */ + short index = 1; + OSErr gErr; + char_u dirname[256]; + char_u cfilename[256]; + long dirID; + char_u *new_name; + CInfoPBRec gMyCPB; + HParamBlockRec gMyHPBlock; + FSSpec usedDir; + + char_u *buf; + char_u *p, *s, *e, dany; + int start_len, c; + char_u *pat; + regmatch_T regmatch; + + start_len = gap->ga_len; + buf = alloc(STRLEN(path) + BASENAMELEN + 5);/* make room for file name */ + if (buf == NULL) + return 0; + +/* + * Find the first part in the path name that contains a wildcard. + * Copy it into buf, including the preceding characters. + */ + p = buf; + s = buf; + e = NULL; +#if 1 + STRNCPY(buf, path, start_at); + p += start_at; + path += start_at; +#endif + + while (*path) + { + if (*path == ':') + { + if (e) + break; + else + s = p + 1; + } + /* should use WILCARDLIST but what about ` */ + /* if (vim_strchr((char_u *)"*?[{~$", *path) != NULL)*/ + else if (vim_strchr((char_u *)WILDCHAR_LIST, *path) != NULL) + e = p; +#ifdef FEAT_MBYTE + if (has_mbyte) + { + int len = (*mb_ptr2len_check)(path); + + STRNCPY(p, path, len); + p += len; + path += len; + } + else +#endif + *p++ = *path++; + } + e = p; + + /* now we have one wildcard component between s and e */ + *e = NUL; + +#if 1 + dany = *s; + *s = NUL; + backslash_halve(buf); + *s = dany; +#endif + + /* convert the file pattern to a regexp pattern */ + pat = file_pat_to_reg_pat(s, e, NULL, FALSE); + if (pat == NULL) + { + vim_free(buf); + return 0; + } + + /* compile the regexp into a program */ + regmatch.rm_ic = FALSE; /* Don't ever ignore case */ + regmatch.regprog = vim_regcomp(pat, RE_MAGIC); + vim_free(pat); + + if (regmatch.regprog == NULL) + { + vim_free(buf); + return 0; + } + + /* open the directory for scanning */ + c = *s; + *s = NUL; + + if (*buf == NUL) + { + as_full = TRUE; +#if 0 + (void) mch_dirname (&dirname[1], 254); + dirname[0] = STRLEN(&dirname[1]); +#endif + } + else + { + if (*buf == ':') /* relative path */ + { + (void)mch_dirname(&dirname[1], 254); + new_name = concat_fnames(&dirname[1], buf+1, TRUE); + STRCPY(&dirname[1], new_name); + dirname[0] = STRLEN(new_name); + vim_free(new_name); + } + else + { + STRCPY(&dirname[1], buf); + backslash_halve(&dirname[1]); + dirname[0] = STRLEN(buf); + } + } + *s = c; + + FSMakeFSSpec (0, 0, dirname, &usedDir); + + gMyCPB.dirInfo.ioNamePtr = dirname; + gMyCPB.dirInfo.ioVRefNum = usedDir.vRefNum; + gMyCPB.dirInfo.ioFDirIndex = 0; + gMyCPB.dirInfo.ioDrDirID = 0; + + gErr = PBGetCatInfo(&gMyCPB, false); + + gMyCPB.dirInfo.ioCompletion = NULL; + dirID = gMyCPB.dirInfo.ioDrDirID; + do + { + gMyCPB.hFileInfo.ioFDirIndex = index; + gMyCPB.hFileInfo.ioDirID = dirID; + + gErr = PBGetCatInfo(&gMyCPB,false); + + if (gErr == noErr) + { + STRNCPY (cfilename, &dirname[1], dirname[0]); + cfilename[dirname[0]] = 0; + if (vim_regexec(®match, cfilename, (colnr_T)0)) + { + if (s[-1] != ':') + { + /* TODO: need to copy with cleaned name */ + STRCPY(s+1, cfilename); + s[0] = ':'; + } + else + { /* TODO: need to copy with cleeaned name */ + STRCPY(s, cfilename); + } + start_at = STRLEN(buf); + STRCAT(buf, path); + if (mch_has_exp_wildcard(path)) /* handle more wildcards */ + (void)mac_expandpath(gap, buf, flags, start_at, FALSE); + else + { +#ifdef DONT_ADD_PATHSEP_TO_DIR + if ((gMyCPB.hFileInfo.ioFlAttrib & ioDirMask) !=0 ) + STRCAT(buf, PATHSEPSTR); +#endif + addfile(gap, buf, flags); + } + } + if ((gMyCPB.hFileInfo.ioFlAttrib & ioDirMask) !=0 ) + { + } + else + { + } + } + index++; + } + while (gErr == noErr); + + if (as_full) + { + index = 1; + do + { + gMyHPBlock.volumeParam.ioNamePtr = (char_u *) dirname; + gMyHPBlock.volumeParam.ioVRefNum =0; + gMyHPBlock.volumeParam.ioVolIndex = index; + + gErr = PBHGetVInfo (&gMyHPBlock,false); + if (gErr == noErr) + { + STRNCPY (cfilename, &dirname[1], dirname[0]); + cfilename[dirname[0]] = 0; + if (vim_regexec(®match, cfilename, (colnr_T)0)) + { + STRCPY(s, cfilename); + STRCAT(buf, path); + if (mch_has_exp_wildcard(path)) /* handle more wildcards */ + (void)mac_expandpath(gap, s, flags, 0, FALSE); + else + { +#ifdef DONT_ADD_PATHSEP_TO_DIR +/* if ((gMyCPB.hFileInfo.ioFlAttrib & ioDirMask) !=0 ) +*/ STRCAT(buf, PATHSEPSTR); +#endif + addfile(gap, s, flags); + } +#if 0 + STRCAT(cfilename, PATHSEPSTR); + addfile (gap, cfilename, flags); +#endif + } + } + index++; + } + while (gErr == noErr); + } + + vim_free(regmatch.regprog); + + return gap->ga_len - start_len; +} + + +#ifdef USE_UNIXFILENAME + static int +pstrcmp(a, b) + const void *a, *b; +{ + return (pathcmp(*(char **)a, *(char **)b)); +} + + static int +unix_expandpath(gap, path, wildoff, flags) + garray_T *gap; + char_u *path; + int wildoff; + int flags; /* EW_* flags */ +{ + char_u *buf; + char_u *path_end; + char_u *p, *s, *e; + int start_len, c; + char_u *pat; + DIR *dirp; + regmatch_T regmatch; + struct dirent *dp; + int starts_with_dot; + int matches; + int len; + + start_len = gap->ga_len; + buf = alloc(STRLEN(path) + BASENAMELEN + 5);/* make room for file name */ + if (buf == NULL) + return 0; + +/* + * Find the first part in the path name that contains a wildcard. + * Copy it into buf, including the preceding characters. + */ + p = buf; + s = buf; + e = NULL; + path_end = path; + while (*path_end) + { + /* May ignore a wildcard that has a backslash before it */ + if (path_end >= path + wildoff && rem_backslash(path_end)) + *p++ = *path_end++; + else if (*path_end == '/') + { + if (e != NULL) + break; + else + s = p + 1; + } + else if (vim_strchr((char_u *)"*?[{~$", *path_end) != NULL) + e = p; +#ifdef FEAT_MBYTE + if (has_mbyte) + { + len = (*mb_ptr2len_check)(path_end); + STRNCPY(p, path_end, len); + p += len; + path_end += len; + } + else +#endif + *p++ = *path_end++; + } + e = p; + *e = NUL; + + /* now we have one wildcard component between s and e */ + /* Remove backslashes between "wildoff" and the start of the wildcard + * component. */ + for (p = buf + wildoff; p < s; ++p) + if (rem_backslash(p)) + { + STRCPY(p, p + 1); + --e; + --s; + } + + /* convert the file pattern to a regexp pattern */ + starts_with_dot = (*s == '.'); + pat = file_pat_to_reg_pat(s, e, NULL, FALSE); + if (pat == NULL) + { + vim_free(buf); + return 0; + } + + /* compile the regexp into a program */ +#ifdef MACOS_X + /* We want to behave like Terminal.app */ + regmatch.rm_ic = TRUE; +#else + regmatch.rm_ic = FALSE; /* Don't ever ignore case */ +#endif + regmatch.regprog = vim_regcomp(pat, RE_MAGIC); + vim_free(pat); + + if (regmatch.regprog == NULL) + { + vim_free(buf); + return 0; + } + + /* open the directory for scanning */ + c = *s; + *s = NUL; + dirp = opendir(*buf == NUL ? "." : (char *)buf); + *s = c; + + /* Find all matching entries */ + if (dirp != NULL) + { + for (;;) + { + dp = readdir(dirp); + if (dp == NULL) + break; + if ((dp->d_name[0] != '.' || starts_with_dot) + && vim_regexec(®match, (char_u *)dp->d_name, (colnr_T)0)) + { + STRCPY(s, dp->d_name); + len = STRLEN(buf); + STRCPY(buf + len, path_end); + if (mch_has_exp_wildcard(path_end)) /* handle more wildcards */ + { + /* need to expand another component of the path */ + /* remove backslashes for the remaining components only */ + (void)unix_expandpath(gap, buf, len + 1, flags); + } + else + { + /* no more wildcards, check if there is a match */ + /* remove backslashes for the remaining components only */ + if (*path_end) + backslash_halve(buf + len + 1); + if (mch_getperm(buf) >= 0) /* add existing file */ + addfile(gap, buf, flags); + } + } + } + + closedir(dirp); + } + + vim_free(buf); + vim_free(regmatch.regprog); + + matches = gap->ga_len - start_len; + if (matches) + qsort(((char_u **)gap->ga_data) + start_len, matches, + sizeof(char_u *), pstrcmp); + return matches; +} +#endif + +/* + * Recursively build up a list of files in "gap" matching the first wildcard + * in `path'. Called by expand_wildcards(). + * "pat" has backslashes before chars that are not to be expanded. + */ + int +mch_expandpath( + garray_T *gap, + char_u *path, + int flags) /* EW_* flags */ +{ +#ifdef USE_UNIXFILENAME + return unix_expandpath(gap, path, 0, flags); +#else + char_u first = *path; + short scan_volume; + + slash_n_colon_adjust(path); + + scan_volume = (first != *path); + + return mac_expandpath(gap, path, flags, 0, scan_volume); +#endif +} + + void +fname_case(name, len) + char_u *name; + int len; /* buffer size, ignored here */ +{ + /* + * TODO: get the real casing for the file + * make it called + * with USE_FNAME_CASE & USE_LONG_FNAME + * CASE_INSENSITIVE_FILENAME + * within setfname, fix_fname, do_ecmd + */ +#ifdef USE_UNIXFILENAME + OSStatus status; + FSRef refFile; + UInt32 pathSize = STRLEN(name) + 1; + char_u *path; + Boolean isDirectory; + + path = alloc(pathSize); + if (path == NULL) + return; + + status = FSPathMakeRef((UInt8 *)name, &refFile, &isDirectory); + if (status) + return; + + status = FSRefMakePath(&refFile, (UInt8 *)path, pathSize); + if (status) + return; + + /* Paranoid: Update the name if only the casing differ.*/ + if (STRICMP(name, path) == 0) + STRCPY(name, path); +#endif +} +static char_u *oldtitle = (char_u *) "gVim"; + +/* + * check for an "interrupt signal": CTRL-break or CTRL-C + */ + void +mch_breakcheck() +{ + /* + * TODO: Scan event for a CTRL-C or COMMAND-. and do: got_int=TRUE; + * or only go proccess event? + * or do nothing + */ + EventRecord theEvent; + + if (EventAvail (keyDownMask, &theEvent)) + if ((theEvent.message & charCodeMask) == Ctrl_C && ctrl_c_interrupts) + got_int = TRUE; +#if 0 + short i = 0; + Boolean found = false; + EventRecord theEvent; + + while ((i < 10) && (!found)) + { + found = EventAvail (keyDownMask, &theEvent); + if (found) + { + if ((theEvent.modifiers & controlKey) != 0) + found = false; + if ((theEvent.what == keyDown)) + found = false; + if ((theEvent.message & charCodeMask) == Ctrl_C) + { + found = false; + got_int = TRUE; + } + } + i++; + } +#endif + +} + +/* + * Return amount of memory currently available. + */ + long_u +mch_avail_mem(special) + int special; +{ + /* + * TODO: Use MaxBlock, FreeMeM, PurgeSpace, MaxBlockSys FAQ-266 + * figure out what the special is for + * + * FreeMem -> returns all avail memory is application heap + * MaxBlock -> returns the biggest contigeous block in application heap + * PurgeSpace -> + */ + return MaxBlock(); +} + + void +mch_delay(msec, ignoreinput) + long msec; + int ignoreinput; +{ +#if (defined(__MWERKS__) && __MWERKS__ >= 0x2000) \ + || defined(__MRC__) || defined(__SC__) + unsigned +#endif + long finalTick; + + if (ignoreinput) + Delay (60*msec/1000, &finalTick); + else + /* even thougth we should call gui stuff from here + it the simplest way to be safe */ + gui_mch_wait_for_chars(msec); +} + + void +mch_init() +{ + /* + * TODO: Verify if needed, or override later. + */ + Columns = 80; + Rows = 24; +} + +/* + * Check_win checks whether we have an interactive stdout. + */ + int +mch_check_win(argc, argv) + int argc; + char **argv; +{ + /* + * TODO: Maybe to be remove through NO_CONSOLE + */ + return OK; +} + +/* + * Return TRUE if the input comes from a terminal, FALSE otherwise. + */ + int +mch_input_isatty() +{ + /* + * TODO: Maybe to be remove through NO_CONSOLE + */ + return OK; +} + +#ifdef FEAT_TITLE +/* + * Set the window title and icon. + * (The icon is not taken care of). + */ + void +mch_settitle(title, icon) + char_u *title; + char_u *icon; +{ + gui_mch_settitle(title, icon); +} + +/* + * Restore the window/icon title. + * which is one of: + * 1 Just restore title + * 2 Just restore icon + * 3 Restore title and icon + * but don't care about the icon. + */ + void +mch_restore_title(which) + int which; +{ + mch_settitle((which & 1) ? oldtitle : NULL, NULL); +} +#endif + +/* + * Insert user name in s[len]. + * Return OK if a name found. + */ + int +mch_get_user_name(s, len) + char_u *s; + int len; +{ +#if !(defined(__MRC__) || defined(__SC__)) /* No solution yet */ + /* + * TODO: clean up and try getlogin () + */ +#if defined(HAVE_PWD_H) && defined(HAVE_GETPWUID) + struct passwd *pw; +#endif + uid_t uid; + + uid = getuid(); +#if defined(HAVE_PWD_H) && defined(HAVE_GETPWUID) + if ((pw = getpwuid(uid)) != NULL + && pw->pw_name != NULL && *(pw->pw_name) != NUL) + { + STRNCPY(s, pw->pw_name, len); + return OK; + } +#endif + sprintf((char *)s, "%d", (int)uid); /* assumes s is long enough */ +#endif + return FAIL; /* a number is not a name */ +} + +/* + * Copy host name into s[len]. + */ + void +mch_get_host_name(s, len) + char_u *s; + int len; +{ +#if defined(__MRC__) || defined(__SC__) || defined(__APPLE_CC__) + STRNCPY(s, "Mac", len); /* TODO: use Gestalt information */ +#else + struct utsname vutsname; + + if (uname(&vutsname) < 0) + *s = NUL; + else + STRNCPY(s, vutsname.nodename, len); +#endif + s[len - 1] = NUL; /* make sure it's terminated */ +} + +/* + * return process ID + */ + long +mch_get_pid() +{ + return (long)getpid(); +} + +/* + * Get name of current directory into buffer 'buf' of length 'len' bytes. + * Return OK for success, FAIL for failure. + */ + int +mch_dirname(buf, len) + char_u *buf; + int len; +{ +#if defined(__MRC__) || defined(__SC__) + return FAIL; /* No solution yet */ +#else + /* The last : is already put by getcwd */ + if (getcwd((char *)buf, len) == NULL) + { + STRCPY(buf, strerror(errno)); + return FAIL; + } +# ifndef USE_UNIXFILENAME + else if (*buf != NUL && buf[STRLEN(buf) - 1] == ':') + buf[STRLEN(buf) - 1] = NUL; /* remove trailing ':' */ +# endif + return OK; +#endif +} + + void +slash_to_colon(p) + char_u *p; +{ + for ( ; *p; ++p) + if (*p == '/') + *p = ':'; +} + + char_u * +slash_to_colon_save (p) + char_u *p; +{ + char_u *res; + + res = vim_strsave(p); + if (res == NULL) + return p; + slash_to_colon(res); + return res; +} + + void +slash_n_colon_adjust (buf) + char_u *buf; +{ + /* + * TODO: Make it faster + */ +#ifndef USE_UNIXFILENAME + char_u temp[MAXPATHL]; + char_u *first_colon = vim_strchr(buf, ':'); + char_u *first_slash = vim_strchr(buf, '/'); + int full = TRUE; + char_u *scanning; + char_u *filling; + char_u last_copied = NUL; + + if (*buf == NUL) + return ; + + if ((first_colon == NULL) && (first_slash == NULL)) + full = FALSE; + if ((first_slash == NULL) && (first_colon != NULL)) + full = TRUE; + if ((first_colon == NULL) && (first_slash != NULL)) + full = FALSE; + if ((first_slash < first_colon) && (first_slash != NULL)) + full = FALSE; + if ((first_colon < first_slash) && (first_colon != NULL)) + full = TRUE; + if (first_slash == buf) + full = TRUE; + if (first_colon == buf) + full = FALSE; + + scanning = buf; + filling = temp; + + while (*scanning != NUL) + { + if (*scanning == '/') + { + if ((scanning[1] != '/') && (scanning[-1] != ':')) + { + *filling++ = ':'; + scanning++; + } + else + scanning++; + } + else if (*scanning == '.') + { + if ((scanning[1] == NUL) || scanning[1] == '/') + { + if (scanning[1] == NUL) + scanning += 1; + else + scanning += 2; + } + else if (scanning[1] == '.') + { + if ((scanning[2] == NUL) || scanning[2] == '/') + { + *filling++ = ':'; + if (scanning[2] == NUL) + scanning +=2; + else + scanning += 3; + } + else + { + *filling++ = *scanning++; + } + } + else + { + *filling++ = *scanning++; + } + + } + else + { + *filling++ = *scanning++; + } + + } + + *filling = 0; + filling = temp; + + if (!full) + { + if (buf[0] != ':') + { + buf[0] = ':'; + buf[1] = NUL; + } + else + buf[0] = NUL; + } + else + { + buf[0] = NUL; + if (filling[0] == ':') + filling++; + } + + STRCAT (buf, filling); +#endif +} + +/* + * Get absolute filename into buffer 'buf' of length 'len' bytes. + * + * return FAIL for failure, OK for success + */ + int +mch_FullName(fname, buf, len, force) + char_u *fname, *buf; + int len; + int force; /* also expand when already absolute path name */ +{ + /* + * TODO: Find what TODO + */ + int l; + char_u olddir[MAXPATHL]; + char_u newdir[MAXPATHL]; + char_u *p; + char_u c; + int retval = OK; + + if (force || !mch_isFullName(fname)) + { + /* + * Forced or not an absolute path. + * If the file name has a path, change to that directory for a moment, + * and then do the getwd() (and get back to where we were). + * This will get the correct path name with "../" things. + */ + if ((p = vim_strrchr(fname, ':')) != NULL) + { + p++; + if (mch_dirname(olddir, MAXPATHL) == FAIL) + { + p = NULL; /* can't get current dir: don't chdir */ + retval = FAIL; + } + else + { + c = *p; + *p = NUL; + if (mch_chdir((char *)fname)) + retval = FAIL; + else + fname = p; /* + 1;*/ + *p = c; + } + } + if (mch_dirname(buf, len) == FAIL) + { + retval = FAIL; + *newdir = NUL; + } + l = STRLEN(buf); + if (STRCMP(fname, ".") != 0) + { +#ifdef USE_UNIXFILENAME + if (l > 0 && buf[l - 1] != '/' && *fname != NUL) + STRCAT(buf, "/"); +#else + if (l > 0 && buf[l - 1] != ':' && *fname != NUL) + STRCAT(buf, ":"); +#endif + } + if (p != NULL) + mch_chdir((char *)olddir); + if (STRCMP(fname, ".") != 0) + STRCAT(buf, fname); + } + else + { + STRNCPY(buf, fname, len); + buf[len - 1] = NUL; + slash_n_colon_adjust(buf); + } + + return retval; +} + +/* + * Return TRUE if "fname" does not depend on the current directory. + */ + int +mch_isFullName(fname) + char_u *fname; +{ +#ifdef USE_UNIXFILENAME + return ((fname[0] == '/') || (fname[0] == '~')); +#else + /* + * TODO: Make sure fname is always of mac still + * i.e: passed throught slash_n_colon_adjust + */ + char_u *first_colon = vim_strchr(fname, ':'); + char_u *first_slash = vim_strchr(fname, '/'); + + if (first_colon == fname) + return FALSE; + if (first_slash == fname) + return TRUE; + if ((first_colon < first_slash) && (first_colon != NULL)) + return TRUE; + if ((first_slash < first_colon) && (first_slash != NULL)) + return FALSE; + if ((first_colon == NULL) && (first_slash != NULL)) + return FALSE; + if ((first_slash == NULL) && (first_colon != NULL)) + return TRUE; + if ((first_colon == NULL) && (first_slash == NULL)) + return FALSE; + return TRUE; +#endif +} + +/* + * Replace all slashes by colons. + */ + void +slash_adjust(p) + char_u *p; +{ +#ifndef USE_UNIXFILENAME + /* + * TODO: keep escaped '/' + */ + + while (*p) + { + if (*p == '/') + *p = ':'; +#ifdef FEAT_MBYTE + if (has_mbyte) + p += (*mb_ptr2len_check)(p); + else +#endif + ++p; + } +#endif +} + +/* + * Get file permissions for 'name'. + * Returns -1 when it doesn't exist. + */ + long +mch_getperm(name) + char_u *name; +{ + /* + * TODO: Maybe use AppleShare info?? + * Use locked for non writable + */ + + struct stat statb; + + if (stat((char *)name, &statb)) + return -1; + return statb.st_mode; +} + +/* + * set file permission for 'name' to 'perm' + * + * return FAIL for failure, OK otherwise + */ + int +mch_setperm(name, perm) + char_u *name; + long perm; +{ + /* + * TODO: Maybe use AppleShare info?? + * Use locked for non writable + */ + return (OK); +} + +/* + * Set hidden flag for "name". + */ + void +mch_hide(name) + char_u *name; +{ + /* + * TODO: Hide the file throught FileManager FAQ 8-34 + * + * *name is mac style start with : for relative + */ +} + + +/* + * return TRUE if "name" is a directory + * return FALSE if "name" is not a directory + * return FALSE for error + */ + int +mch_isdir(name) + char_u *name; +{ + /* + * TODO: Find out by FileManager calls ... + */ + struct stat statb; + +#if defined(TARGET_API_MAC_CARBON) && TARGET_API_MAC_CARBON + /* For some reason the name is sometimes empty, + * (such as for a not yet named file). An empty + * filename is interpreted by the MacOS version + * of stat (at least under Codewarrior) as the + * current directory. + */ + /* AK 20020413 + * This is required for Carbon but breaks the + * explorer plugin in Classic + */ + if (name[0] == NULL) + return FALSE; +#endif + + if (stat((char *)name, &statb)) + return FALSE; +#if defined(__MRC__) || defined(__SC__) + return FALSE; /* definitely TODO */ +#else + return ((statb.st_mode & S_IFMT) == S_IFDIR ? TRUE : FALSE); +#endif +} + +#if defined(FEAT_EVAL) || defined(PROTO) +/* + * Return 1 if "name" can be executed, 0 if not. + * Return -1 if unknown. + */ + int +mch_can_exe(name) + char_u *name; +{ + /* TODO */ + return -1; +} +#endif + +/* + * Check what "name" is: + * NODE_NORMAL: file or directory (or doesn't exist) + * NODE_WRITABLE: writable device, socket, fifo, etc. + * NODE_OTHER: non-writable things + */ + int +mch_nodetype(name) + char_u *name; +{ + /* TODO */ + return NODE_NORMAL; +} + + void +mch_early_init() +{ +} + + void +mch_exit(r) + int r; +{ + display_errors(); + + ml_close_all(TRUE); /* remove all memfiles */ + exit(r); +} + + + void +mch_settmode(tmode) + int tmode; +{ + /* + * TODO: remove the needs of it. + */ +} + +#ifdef FEAT_MOUSE +/* + * set mouse clicks on or off (only works for xterms) + */ + void +mch_setmouse(on) + int on; +{ + /* + * TODO: remove the needs of it. + */ +} +#endif + +/* + * set screen mode, always fails. + */ + int +mch_screenmode(arg) + char_u *arg; +{ + EMSG(_(e_screenmode)); + return FAIL; +} + + int +mch_call_shell(cmd, options) + char_u *cmd; + int options; /* SHELL_*, see vim.h */ +{ + /* + * TODO: find a shell or pseudo-shell to call + * for some simple useful command + */ + + return (-1); +} + +/* + * Return TRUE if "p" contains a wildcard that can be expanded by + * mch_expandpath(). + */ + int +mch_has_exp_wildcard(p) + char_u *p; +{ + for ( ; *p; ++p) + { + if (*p == '\\' && p[1] != NUL) + ++p; + else if (vim_strchr((char_u *)WILDCHAR_LIST, *p) != NULL) + return TRUE; +#ifdef FEAT_MBYTE + if (has_mbyte) + p += (*mb_ptr2len_check)(p) - 1; +#endif + } + return FALSE; +} + + int +mch_has_wildcard(p) + char_u *p; +{ +#ifdef USE_UNIXFILENAME + if (*p == '~' && p[1] != NUL) + return TRUE; +#endif + return mch_has_exp_wildcard(p); +} + + +/* + * This procedure duplicate a file, it is used in order to keep + * the footprint of the previous file, when some info can be easily + * restored with set_perm(). + * + * Return -1 for failure, 0 for success. + */ + int +mch_copy_file(from, to) + char_u *from; + char_u *to; +{ + char_u from_str[256]; + char_u to_str[256]; + char_u to_name[256]; + + HParamBlockRec paramBlock; + char_u *char_ptr; + int len; + + /* + * Convert C string to Pascal string + */ + char_ptr = from; + len = 1; + for (; (*char_ptr != 0) && (len < 255); len++, char_ptr++) + from_str[len] = *char_ptr; + from_str[0] = len-1; + + char_ptr = to; + len = 1; + for (; (*char_ptr != 0) && (len < 255); len++, char_ptr++) + to_str[len] = *char_ptr; + to_str[0] = len-1; + + paramBlock.copyParam.ioCompletion = NULL; + paramBlock.copyParam.ioNamePtr = from_str; + /* paramBlock.copyParam.ioVRefnum = overided by ioFilename; */ + /* paramBlock.copyParam.ioDirI = overided by ioFilename; */ + + paramBlock.copyParam.ioNewName = to_str; + paramBlock.copyParam.ioCopyName = to_name; /* NIL */ + /* paramBlock.copyParam.ioDstVRefNum = overided by ioNewName; */ + /* paramBlock.copyParam.ioNewDirID = overided by ioNewName; */ + + + + /* + * First delete the "to" file, this is required on some systems to make + * the rename() work, on other systems it makes sure that we don't have + * two files when the rename() fails. + */ + mch_remove(to); + + /* + * First try a normal rename, return if it works. + */ + (void) PBHCopyFile(¶mBlock, false); + return 0; + +} + + + int +mch_copy_file_attribute(from, to) + char_u *from; + char_u *to; +{ + FSSpec frFSSpec; + FSSpec toFSSpec; + FInfo fndrInfo; + Str255 name; + ResType type; + ResType sink; + Handle resource; + short idxTypes; + short nbTypes; + short idxResources; + short nbResources; + short ID; + short frRFid; + short toRFid; + short attrs_orig; + short attrs_copy; + short temp; + + /* TODO: Handle error */ + (void) GetFSSpecFromPath (from, &frFSSpec); + (void) GetFSSpecFromPath (to , &toFSSpec); + + /* Copy resource fork */ + temp = 0; + +#if 1 + frRFid = FSpOpenResFile (&frFSSpec, fsCurPerm); + + if (frRFid != -1) + { + FSpCreateResFile(&toFSSpec, 'TEXT', UNKNOWN_CREATOR, 0); + toRFid = FSpOpenResFile (&toFSSpec, fsRdWrPerm); + + UseResFile (frRFid); + + nbTypes = Count1Types(); + + for (idxTypes = 1; idxTypes <= nbTypes; idxTypes++) + { + Get1IndType (&type, idxTypes); + nbResources = Count1Resources(type); + + for (idxResources = 1; idxResources <= nbResources; idxResources++) + { + attrs_orig = 0; /* in case GetRes fails */ + attrs_copy = 0; /* in case GetRes fails */ + resource = Get1IndResource(type, idxResources); + GetResInfo (resource, &ID, &sink, name); + HLock (resource); + attrs_orig = GetResAttrs (resource); + DetachResource (resource); + + + UseResFile (toRFid); + AddResource (resource, type, ID, name); + attrs_copy = GetResAttrs (resource); + attrs_copy = (attrs_copy & 0x2) | (attrs_orig & 0xFD); + SetResAttrs (resource, attrs_copy); + WriteResource (resource); + UpdateResFile (toRFid); + + temp = GetResAttrs (resource); + + /*SetResAttrs (resource, 0);*/ + HUnlock(resource); + ReleaseResource (resource); + UseResFile (frRFid); + } + } + CloseResFile (toRFid); + CloseResFile (frRFid); + } +#endif + /* Copy Finder Info */ + (void) FSpGetFInfo (&frFSSpec, &fndrInfo); + (void) FSpSetFInfo (&toFSSpec, &fndrInfo); + + return (temp == attrs_copy); +} + + int +mch_has_resource_fork (file) + char_u *file; +{ + FSSpec fileFSSpec; + short fileRFid; + + /* TODO: Handle error */ + (void) GetFSSpecFromPath (file, &fileFSSpec); + fileRFid = FSpOpenResFile (&fileFSSpec, fsCurPerm); + if (fileRFid != -1) + CloseResFile (fileRFid); + + return (fileRFid != -1); +} + + int +mch_get_shellsize(void) +{ + /* never used */ + return OK; +} + + void +mch_set_shellsize(void) +{ + /* never used */ +} + +/* + * Rows and/or Columns has changed. + */ + void +mch_new_shellsize(void) +{ + /* never used */ +} + +/* + * Those function were set as #define before, but in order + * to allow an easier us of os_unix.c for the MacOS X port, + * they are change to procedure. Thec ompile whould optimize + * them out. + */ + + int +mch_can_restore_title() +{ + return TRUE; +} + + int +mch_can_restore_icon() +{ + return TRUE; +} + +/* + * If the machine has job control, use it to suspend the program, + * otherwise fake it by starting a new shell. + */ + void +mch_suspend() +{ + /* TODO: get calle in #ifndef NO_CONSOLE */ + gui_mch_iconify(); +}; + |