updated for version 7.0001
diff --git a/src/os_mac.c b/src/os_mac.c
new file mode 100644
index 0000000..0f6a76c
--- /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(&regmatch, 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(&regmatch, 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(&regmatch, (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(&paramBlock, 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();
+};
+