blob: fbfb11ce61e8b20c22faa9408255e24ffd775431 [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001/* vi:set ts=8 sts=4 sw=4:
2 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9
10/*
11 * os_mac.c -- code for the MacOS
12 *
13 * This file is mainly based on os_unix.c.
14 */
15
16#include "vim.h"
17
18#if defined(__MRC__) || defined(__SC__) /* for Apple MPW Compilers */
19
20#include "StandardFile.h"
21
22/*
23 * Implements the corresponding unix function
24 */
25 int
26stat(
27 char *p,
28 struct stat *p_st)
29{
30 /*
31 TODO: Use functions which fill the FileParam struct (Files.h)
32 and copy these contents to our self-defined stat struct
33 */
34 return 0;
35}
36#endif
37
38/*
39 * change the current working directory
40 */
41 int
42mch_chdir(char *p_name)
43{
44#if defined(__MRC__) || defined(__SC__) /* for Apple MPW Compilers */
45 /* TODO */
46 return FAIL;
47#else
48 return chdir(p_name);
49#endif
50}
51
52
53/*
54 * Recursively build up a list of files in "gap" matching the first wildcard
55 * in `path'. Called by mch_expandpath().
56 * "path" has backslashes before chars that are not to be expanded.
57 */
Bram Moolenaar02743632005-07-25 20:42:36 +000058 static int
Bram Moolenaar071d4272004-06-13 20:20:40 +000059mac_expandpath(
60 garray_T *gap,
61 char_u *path,
62 int flags, /* EW_* flags */
63 short start_at,
64 short as_full)
65{
66 /*
67 * TODO:
68 * +Get Volumes (when looking for files in current dir)
69 * +Make it work when working dir not on select volume
70 * +Cleanup
71 */
72 short index = 1;
73 OSErr gErr;
74 char_u dirname[256];
75 char_u cfilename[256];
76 long dirID;
77 char_u *new_name;
78 CInfoPBRec gMyCPB;
79 HParamBlockRec gMyHPBlock;
80 FSSpec usedDir;
81
82 char_u *buf;
83 char_u *p, *s, *e, dany;
84 int start_len, c;
85 char_u *pat;
86 regmatch_T regmatch;
87
88 start_len = gap->ga_len;
89 buf = alloc(STRLEN(path) + BASENAMELEN + 5);/* make room for file name */
90 if (buf == NULL)
91 return 0;
92
93/*
94 * Find the first part in the path name that contains a wildcard.
95 * Copy it into buf, including the preceding characters.
96 */
97 p = buf;
98 s = buf;
99 e = NULL;
100#if 1
101 STRNCPY(buf, path, start_at);
102 p += start_at;
103 path += start_at;
104#endif
105
106 while (*path)
107 {
108 if (*path == ':')
109 {
110 if (e)
111 break;
Bram Moolenaar02743632005-07-25 20:42:36 +0000112 s = p + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000113 }
114 /* should use WILCARDLIST but what about ` */
115 /* if (vim_strchr((char_u *)"*?[{~$", *path) != NULL)*/
116 else if (vim_strchr((char_u *)WILDCHAR_LIST, *path) != NULL)
117 e = p;
118#ifdef FEAT_MBYTE
119 if (has_mbyte)
120 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +0000121 int len = (*mb_ptr2len)(path);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000122
123 STRNCPY(p, path, len);
124 p += len;
125 path += len;
126 }
127 else
128#endif
129 *p++ = *path++;
130 }
131 e = p;
132
133 /* now we have one wildcard component between s and e */
134 *e = NUL;
135
Bram Moolenaar071d4272004-06-13 20:20:40 +0000136 dany = *s;
137 *s = NUL;
138 backslash_halve(buf);
139 *s = dany;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000140
141 /* convert the file pattern to a regexp pattern */
142 pat = file_pat_to_reg_pat(s, e, NULL, FALSE);
143 if (pat == NULL)
144 {
145 vim_free(buf);
146 return 0;
147 }
148
149 /* compile the regexp into a program */
150 regmatch.rm_ic = FALSE; /* Don't ever ignore case */
151 regmatch.regprog = vim_regcomp(pat, RE_MAGIC);
152 vim_free(pat);
153
154 if (regmatch.regprog == NULL)
155 {
156 vim_free(buf);
157 return 0;
158 }
159
160 /* open the directory for scanning */
161 c = *s;
162 *s = NUL;
163
164 if (*buf == NUL)
165 {
166 as_full = TRUE;
167#if 0
168 (void) mch_dirname (&dirname[1], 254);
169 dirname[0] = STRLEN(&dirname[1]);
170#endif
171 }
172 else
173 {
174 if (*buf == ':') /* relative path */
175 {
176 (void)mch_dirname(&dirname[1], 254);
177 new_name = concat_fnames(&dirname[1], buf+1, TRUE);
178 STRCPY(&dirname[1], new_name);
179 dirname[0] = STRLEN(new_name);
180 vim_free(new_name);
181 }
182 else
183 {
184 STRCPY(&dirname[1], buf);
185 backslash_halve(&dirname[1]);
186 dirname[0] = STRLEN(buf);
187 }
188 }
189 *s = c;
190
191 FSMakeFSSpec (0, 0, dirname, &usedDir);
192
193 gMyCPB.dirInfo.ioNamePtr = dirname;
194 gMyCPB.dirInfo.ioVRefNum = usedDir.vRefNum;
195 gMyCPB.dirInfo.ioFDirIndex = 0;
196 gMyCPB.dirInfo.ioDrDirID = 0;
197
198 gErr = PBGetCatInfo(&gMyCPB, false);
199
200 gMyCPB.dirInfo.ioCompletion = NULL;
201 dirID = gMyCPB.dirInfo.ioDrDirID;
202 do
203 {
204 gMyCPB.hFileInfo.ioFDirIndex = index;
205 gMyCPB.hFileInfo.ioDirID = dirID;
206
Bram Moolenaar02743632005-07-25 20:42:36 +0000207 gErr = PBGetCatInfo(&gMyCPB, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000208
209 if (gErr == noErr)
210 {
Bram Moolenaarb6356332005-07-18 21:40:44 +0000211 vim_strncpy(cfilename, &dirname[1], dirname[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000212 if (vim_regexec(&regmatch, cfilename, (colnr_T)0))
213 {
214 if (s[-1] != ':')
215 {
216 /* TODO: need to copy with cleaned name */
217 STRCPY(s+1, cfilename);
218 s[0] = ':';
219 }
220 else
221 { /* TODO: need to copy with cleeaned name */
222 STRCPY(s, cfilename);
223 }
224 start_at = STRLEN(buf);
225 STRCAT(buf, path);
226 if (mch_has_exp_wildcard(path)) /* handle more wildcards */
227 (void)mac_expandpath(gap, buf, flags, start_at, FALSE);
228 else
229 {
230#ifdef DONT_ADD_PATHSEP_TO_DIR
231 if ((gMyCPB.hFileInfo.ioFlAttrib & ioDirMask) !=0 )
232 STRCAT(buf, PATHSEPSTR);
233#endif
234 addfile(gap, buf, flags);
235 }
236 }
Bram Moolenaar02743632005-07-25 20:42:36 +0000237#if 0 /* What is this supposed to do? */
238 if ((gMyCPB.hFileInfo.ioFlAttrib & ioDirMask) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000239 {
240 }
241 else
242 {
243 }
Bram Moolenaar02743632005-07-25 20:42:36 +0000244#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000245 }
246 index++;
247 }
248 while (gErr == noErr);
249
250 if (as_full)
251 {
252 index = 1;
253 do
254 {
255 gMyHPBlock.volumeParam.ioNamePtr = (char_u *) dirname;
Bram Moolenaar02743632005-07-25 20:42:36 +0000256 gMyHPBlock.volumeParam.ioVRefNum = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000257 gMyHPBlock.volumeParam.ioVolIndex = index;
258
259 gErr = PBHGetVInfo (&gMyHPBlock,false);
260 if (gErr == noErr)
261 {
Bram Moolenaarb6356332005-07-18 21:40:44 +0000262 vim_strncpy(cfilename, &dirname[1], dirname[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000263 if (vim_regexec(&regmatch, cfilename, (colnr_T)0))
264 {
265 STRCPY(s, cfilename);
266 STRCAT(buf, path);
267 if (mch_has_exp_wildcard(path)) /* handle more wildcards */
268 (void)mac_expandpath(gap, s, flags, 0, FALSE);
269 else
270 {
271#ifdef DONT_ADD_PATHSEP_TO_DIR
272/* if ((gMyCPB.hFileInfo.ioFlAttrib & ioDirMask) !=0 )
273*/ STRCAT(buf, PATHSEPSTR);
274#endif
275 addfile(gap, s, flags);
276 }
277#if 0
278 STRCAT(cfilename, PATHSEPSTR);
279 addfile (gap, cfilename, flags);
280#endif
281 }
282 }
283 index++;
284 }
285 while (gErr == noErr);
286 }
287
288 vim_free(regmatch.regprog);
289
290 return gap->ga_len - start_len;
291}
292
Bram Moolenaar071d4272004-06-13 20:20:40 +0000293/*
294 * Recursively build up a list of files in "gap" matching the first wildcard
295 * in `path'. Called by expand_wildcards().
296 * "pat" has backslashes before chars that are not to be expanded.
297 */
298 int
299mch_expandpath(
300 garray_T *gap,
301 char_u *path,
302 int flags) /* EW_* flags */
303{
304#ifdef USE_UNIXFILENAME
Bram Moolenaar02743632005-07-25 20:42:36 +0000305 return unix_expandpath(gap, path, 0, flags, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000306#else
307 char_u first = *path;
308 short scan_volume;
309
310 slash_n_colon_adjust(path);
311
312 scan_volume = (first != *path);
313
314 return mac_expandpath(gap, path, flags, 0, scan_volume);
315#endif
316}
317
318 void
319fname_case(name, len)
320 char_u *name;
321 int len; /* buffer size, ignored here */
322{
323 /*
324 * TODO: get the real casing for the file
325 * make it called
326 * with USE_FNAME_CASE & USE_LONG_FNAME
327 * CASE_INSENSITIVE_FILENAME
328 * within setfname, fix_fname, do_ecmd
329 */
330#ifdef USE_UNIXFILENAME
331 OSStatus status;
332 FSRef refFile;
333 UInt32 pathSize = STRLEN(name) + 1;
334 char_u *path;
335 Boolean isDirectory;
336
337 path = alloc(pathSize);
338 if (path == NULL)
339 return;
340
341 status = FSPathMakeRef((UInt8 *)name, &refFile, &isDirectory);
342 if (status)
343 return;
344
345 status = FSRefMakePath(&refFile, (UInt8 *)path, pathSize);
346 if (status)
347 return;
348
349 /* Paranoid: Update the name if only the casing differ.*/
350 if (STRICMP(name, path) == 0)
351 STRCPY(name, path);
352#endif
353}
354static char_u *oldtitle = (char_u *) "gVim";
355
356/*
357 * check for an "interrupt signal": CTRL-break or CTRL-C
358 */
359 void
360mch_breakcheck()
361{
362 /*
363 * TODO: Scan event for a CTRL-C or COMMAND-. and do: got_int=TRUE;
364 * or only go proccess event?
365 * or do nothing
366 */
367 EventRecord theEvent;
368
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000369 if (EventAvail(keyDownMask, &theEvent))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000370 if ((theEvent.message & charCodeMask) == Ctrl_C && ctrl_c_interrupts)
371 got_int = TRUE;
372#if 0
373 short i = 0;
374 Boolean found = false;
375 EventRecord theEvent;
376
377 while ((i < 10) && (!found))
378 {
379 found = EventAvail (keyDownMask, &theEvent);
380 if (found)
381 {
382 if ((theEvent.modifiers & controlKey) != 0)
383 found = false;
384 if ((theEvent.what == keyDown))
385 found = false;
386 if ((theEvent.message & charCodeMask) == Ctrl_C)
387 {
388 found = false;
389 got_int = TRUE;
390 }
391 }
392 i++;
393 }
394#endif
395
396}
397
398/*
399 * Return amount of memory currently available.
400 */
401 long_u
402mch_avail_mem(special)
403 int special;
404{
405 /*
406 * TODO: Use MaxBlock, FreeMeM, PurgeSpace, MaxBlockSys FAQ-266
407 * figure out what the special is for
408 *
409 * FreeMem -> returns all avail memory is application heap
410 * MaxBlock -> returns the biggest contigeous block in application heap
411 * PurgeSpace ->
412 */
413 return MaxBlock();
414}
415
416 void
417mch_delay(msec, ignoreinput)
418 long msec;
419 int ignoreinput;
420{
421#if (defined(__MWERKS__) && __MWERKS__ >= 0x2000) \
422 || defined(__MRC__) || defined(__SC__)
423 unsigned
424#endif
425 long finalTick;
426
427 if (ignoreinput)
428 Delay (60*msec/1000, &finalTick);
429 else
430 /* even thougth we should call gui stuff from here
431 it the simplest way to be safe */
432 gui_mch_wait_for_chars(msec);
433}
434
435 void
436mch_init()
437{
438 /*
439 * TODO: Verify if needed, or override later.
440 */
441 Columns = 80;
442 Rows = 24;
443}
444
445/*
446 * Check_win checks whether we have an interactive stdout.
447 */
448 int
449mch_check_win(argc, argv)
450 int argc;
451 char **argv;
452{
453 /*
454 * TODO: Maybe to be remove through NO_CONSOLE
455 */
456 return OK;
457}
458
459/*
460 * Return TRUE if the input comes from a terminal, FALSE otherwise.
461 */
462 int
463mch_input_isatty()
464{
465 /*
466 * TODO: Maybe to be remove through NO_CONSOLE
467 */
468 return OK;
469}
470
471#ifdef FEAT_TITLE
472/*
473 * Set the window title and icon.
474 * (The icon is not taken care of).
475 */
476 void
477mch_settitle(title, icon)
478 char_u *title;
479 char_u *icon;
480{
481 gui_mch_settitle(title, icon);
482}
483
484/*
485 * Restore the window/icon title.
486 * which is one of:
487 * 1 Just restore title
488 * 2 Just restore icon
489 * 3 Restore title and icon
490 * but don't care about the icon.
491 */
492 void
493mch_restore_title(which)
494 int which;
495{
496 mch_settitle((which & 1) ? oldtitle : NULL, NULL);
497}
498#endif
499
500/*
501 * Insert user name in s[len].
502 * Return OK if a name found.
503 */
504 int
505mch_get_user_name(s, len)
506 char_u *s;
507 int len;
508{
509#if !(defined(__MRC__) || defined(__SC__)) /* No solution yet */
510 /*
511 * TODO: clean up and try getlogin ()
512 */
513#if defined(HAVE_PWD_H) && defined(HAVE_GETPWUID)
514 struct passwd *pw;
515#endif
516 uid_t uid;
517
518 uid = getuid();
519#if defined(HAVE_PWD_H) && defined(HAVE_GETPWUID)
520 if ((pw = getpwuid(uid)) != NULL
521 && pw->pw_name != NULL && *(pw->pw_name) != NUL)
522 {
Bram Moolenaarb6356332005-07-18 21:40:44 +0000523 vim_strncpy(s, pw->pw_name, len - 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000524 return OK;
525 }
526#endif
527 sprintf((char *)s, "%d", (int)uid); /* assumes s is long enough */
528#endif
529 return FAIL; /* a number is not a name */
530}
531
532/*
533 * Copy host name into s[len].
534 */
535 void
536mch_get_host_name(s, len)
537 char_u *s;
538 int len;
539{
540#if defined(__MRC__) || defined(__SC__) || defined(__APPLE_CC__)
Bram Moolenaarb6356332005-07-18 21:40:44 +0000541 vim_strncpy(s, "Mac", len - 1); /* TODO: use Gestalt information */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000542#else
543 struct utsname vutsname;
544
545 if (uname(&vutsname) < 0)
546 *s = NUL;
547 else
Bram Moolenaarb6356332005-07-18 21:40:44 +0000548 vim_strncpy(s, vutsname.nodename, len - 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000549#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000550}
551
552/*
553 * return process ID
554 */
555 long
556mch_get_pid()
557{
558 return (long)getpid();
559}
560
561/*
562 * Get name of current directory into buffer 'buf' of length 'len' bytes.
563 * Return OK for success, FAIL for failure.
564 */
565 int
566mch_dirname(buf, len)
567 char_u *buf;
568 int len;
569{
570#if defined(__MRC__) || defined(__SC__)
571 return FAIL; /* No solution yet */
572#else
573 /* The last : is already put by getcwd */
574 if (getcwd((char *)buf, len) == NULL)
575 {
576 STRCPY(buf, strerror(errno));
577 return FAIL;
578 }
579# ifndef USE_UNIXFILENAME
580 else if (*buf != NUL && buf[STRLEN(buf) - 1] == ':')
581 buf[STRLEN(buf) - 1] = NUL; /* remove trailing ':' */
582# endif
583 return OK;
584#endif
585}
586
587 void
588slash_to_colon(p)
589 char_u *p;
590{
591 for ( ; *p; ++p)
592 if (*p == '/')
593 *p = ':';
594}
595
596 char_u *
597slash_to_colon_save (p)
598 char_u *p;
599{
600 char_u *res;
601
602 res = vim_strsave(p);
603 if (res == NULL)
604 return p;
605 slash_to_colon(res);
606 return res;
607}
608
609 void
610slash_n_colon_adjust (buf)
611 char_u *buf;
612{
613 /*
614 * TODO: Make it faster
615 */
616#ifndef USE_UNIXFILENAME
617 char_u temp[MAXPATHL];
618 char_u *first_colon = vim_strchr(buf, ':');
619 char_u *first_slash = vim_strchr(buf, '/');
620 int full = TRUE;
621 char_u *scanning;
622 char_u *filling;
623 char_u last_copied = NUL;
624
625 if (*buf == NUL)
626 return ;
627
628 if ((first_colon == NULL) && (first_slash == NULL))
629 full = FALSE;
630 if ((first_slash == NULL) && (first_colon != NULL))
631 full = TRUE;
632 if ((first_colon == NULL) && (first_slash != NULL))
633 full = FALSE;
634 if ((first_slash < first_colon) && (first_slash != NULL))
635 full = FALSE;
636 if ((first_colon < first_slash) && (first_colon != NULL))
637 full = TRUE;
638 if (first_slash == buf)
639 full = TRUE;
640 if (first_colon == buf)
641 full = FALSE;
642
643 scanning = buf;
644 filling = temp;
645
646 while (*scanning != NUL)
647 {
648 if (*scanning == '/')
649 {
650 if ((scanning[1] != '/') && (scanning[-1] != ':'))
651 {
652 *filling++ = ':';
653 scanning++;
654 }
655 else
656 scanning++;
657 }
658 else if (*scanning == '.')
659 {
660 if ((scanning[1] == NUL) || scanning[1] == '/')
661 {
662 if (scanning[1] == NUL)
663 scanning += 1;
664 else
665 scanning += 2;
666 }
667 else if (scanning[1] == '.')
668 {
669 if ((scanning[2] == NUL) || scanning[2] == '/')
670 {
671 *filling++ = ':';
672 if (scanning[2] == NUL)
673 scanning +=2;
674 else
675 scanning += 3;
676 }
677 else
678 {
679 *filling++ = *scanning++;
680 }
681 }
682 else
683 {
684 *filling++ = *scanning++;
685 }
686
687 }
688 else
689 {
690 *filling++ = *scanning++;
691 }
692
693 }
694
695 *filling = 0;
696 filling = temp;
697
698 if (!full)
699 {
700 if (buf[0] != ':')
701 {
702 buf[0] = ':';
703 buf[1] = NUL;
704 }
705 else
706 buf[0] = NUL;
707 }
708 else
709 {
710 buf[0] = NUL;
711 if (filling[0] == ':')
712 filling++;
713 }
714
715 STRCAT (buf, filling);
716#endif
717}
718
719/*
720 * Get absolute filename into buffer 'buf' of length 'len' bytes.
721 *
722 * return FAIL for failure, OK for success
723 */
724 int
725mch_FullName(fname, buf, len, force)
726 char_u *fname, *buf;
727 int len;
728 int force; /* also expand when already absolute path name */
729{
730 /*
731 * TODO: Find what TODO
732 */
733 int l;
734 char_u olddir[MAXPATHL];
735 char_u newdir[MAXPATHL];
736 char_u *p;
737 char_u c;
738 int retval = OK;
739
740 if (force || !mch_isFullName(fname))
741 {
742 /*
743 * Forced or not an absolute path.
744 * If the file name has a path, change to that directory for a moment,
745 * and then do the getwd() (and get back to where we were).
746 * This will get the correct path name with "../" things.
747 */
748 if ((p = vim_strrchr(fname, ':')) != NULL)
749 {
750 p++;
751 if (mch_dirname(olddir, MAXPATHL) == FAIL)
752 {
753 p = NULL; /* can't get current dir: don't chdir */
754 retval = FAIL;
755 }
756 else
757 {
758 c = *p;
759 *p = NUL;
760 if (mch_chdir((char *)fname))
761 retval = FAIL;
762 else
763 fname = p; /* + 1;*/
764 *p = c;
765 }
766 }
767 if (mch_dirname(buf, len) == FAIL)
768 {
769 retval = FAIL;
770 *newdir = NUL;
771 }
772 l = STRLEN(buf);
773 if (STRCMP(fname, ".") != 0)
774 {
775#ifdef USE_UNIXFILENAME
776 if (l > 0 && buf[l - 1] != '/' && *fname != NUL)
777 STRCAT(buf, "/");
778#else
779 if (l > 0 && buf[l - 1] != ':' && *fname != NUL)
780 STRCAT(buf, ":");
781#endif
782 }
783 if (p != NULL)
784 mch_chdir((char *)olddir);
785 if (STRCMP(fname, ".") != 0)
786 STRCAT(buf, fname);
787 }
788 else
789 {
Bram Moolenaarb6356332005-07-18 21:40:44 +0000790 vim_strncpy(buf, fname, len - 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000791 slash_n_colon_adjust(buf);
792 }
793
794 return retval;
795}
796
797/*
798 * Return TRUE if "fname" does not depend on the current directory.
799 */
800 int
801mch_isFullName(fname)
802 char_u *fname;
803{
804#ifdef USE_UNIXFILENAME
805 return ((fname[0] == '/') || (fname[0] == '~'));
806#else
807 /*
808 * TODO: Make sure fname is always of mac still
809 * i.e: passed throught slash_n_colon_adjust
810 */
811 char_u *first_colon = vim_strchr(fname, ':');
812 char_u *first_slash = vim_strchr(fname, '/');
813
814 if (first_colon == fname)
815 return FALSE;
816 if (first_slash == fname)
817 return TRUE;
818 if ((first_colon < first_slash) && (first_colon != NULL))
819 return TRUE;
820 if ((first_slash < first_colon) && (first_slash != NULL))
821 return FALSE;
822 if ((first_colon == NULL) && (first_slash != NULL))
823 return FALSE;
824 if ((first_slash == NULL) && (first_colon != NULL))
825 return TRUE;
826 if ((first_colon == NULL) && (first_slash == NULL))
827 return FALSE;
828 return TRUE;
829#endif
830}
831
832/*
833 * Replace all slashes by colons.
834 */
835 void
836slash_adjust(p)
837 char_u *p;
838{
839#ifndef USE_UNIXFILENAME
840 /*
841 * TODO: keep escaped '/'
842 */
843
844 while (*p)
845 {
846 if (*p == '/')
847 *p = ':';
Bram Moolenaar1cd871b2004-12-19 22:46:22 +0000848 mb_ptr_adv(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000849 }
850#endif
851}
852
853/*
854 * Get file permissions for 'name'.
855 * Returns -1 when it doesn't exist.
856 */
857 long
858mch_getperm(name)
859 char_u *name;
860{
861 /*
862 * TODO: Maybe use AppleShare info??
863 * Use locked for non writable
864 */
865
866 struct stat statb;
867
868 if (stat((char *)name, &statb))
869 return -1;
870 return statb.st_mode;
871}
872
873/*
874 * set file permission for 'name' to 'perm'
875 *
876 * return FAIL for failure, OK otherwise
877 */
878 int
879mch_setperm(name, perm)
880 char_u *name;
881 long perm;
882{
883 /*
884 * TODO: Maybe use AppleShare info??
885 * Use locked for non writable
886 */
887 return (OK);
888}
889
890/*
891 * Set hidden flag for "name".
892 */
893 void
894mch_hide(name)
895 char_u *name;
896{
897 /*
898 * TODO: Hide the file throught FileManager FAQ 8-34
899 *
900 * *name is mac style start with : for relative
901 */
902}
903
904
905/*
906 * return TRUE if "name" is a directory
907 * return FALSE if "name" is not a directory
908 * return FALSE for error
909 */
910 int
911mch_isdir(name)
912 char_u *name;
913{
914 /*
915 * TODO: Find out by FileManager calls ...
916 */
917 struct stat statb;
918
919#if defined(TARGET_API_MAC_CARBON) && TARGET_API_MAC_CARBON
920 /* For some reason the name is sometimes empty,
921 * (such as for a not yet named file). An empty
922 * filename is interpreted by the MacOS version
923 * of stat (at least under Codewarrior) as the
924 * current directory.
925 */
926 /* AK 20020413
927 * This is required for Carbon but breaks the
928 * explorer plugin in Classic
929 */
930 if (name[0] == NULL)
931 return FALSE;
932#endif
933
934 if (stat((char *)name, &statb))
935 return FALSE;
936#if defined(__MRC__) || defined(__SC__)
937 return FALSE; /* definitely TODO */
938#else
939 return ((statb.st_mode & S_IFMT) == S_IFDIR ? TRUE : FALSE);
940#endif
941}
942
943#if defined(FEAT_EVAL) || defined(PROTO)
944/*
945 * Return 1 if "name" can be executed, 0 if not.
946 * Return -1 if unknown.
947 */
948 int
949mch_can_exe(name)
950 char_u *name;
951{
952 /* TODO */
953 return -1;
954}
955#endif
956
957/*
958 * Check what "name" is:
959 * NODE_NORMAL: file or directory (or doesn't exist)
960 * NODE_WRITABLE: writable device, socket, fifo, etc.
961 * NODE_OTHER: non-writable things
962 */
963 int
964mch_nodetype(name)
965 char_u *name;
966{
967 /* TODO */
968 return NODE_NORMAL;
969}
970
971 void
972mch_early_init()
973{
974}
975
976 void
977mch_exit(r)
978 int r;
979{
980 display_errors();
981
982 ml_close_all(TRUE); /* remove all memfiles */
983 exit(r);
984}
985
986
987 void
988mch_settmode(tmode)
989 int tmode;
990{
991 /*
992 * TODO: remove the needs of it.
993 */
994}
995
996#ifdef FEAT_MOUSE
997/*
998 * set mouse clicks on or off (only works for xterms)
999 */
1000 void
1001mch_setmouse(on)
1002 int on;
1003{
1004 /*
1005 * TODO: remove the needs of it.
1006 */
1007}
1008#endif
1009
1010/*
1011 * set screen mode, always fails.
1012 */
1013 int
1014mch_screenmode(arg)
1015 char_u *arg;
1016{
1017 EMSG(_(e_screenmode));
1018 return FAIL;
1019}
1020
1021 int
1022mch_call_shell(cmd, options)
1023 char_u *cmd;
1024 int options; /* SHELL_*, see vim.h */
1025{
1026 /*
1027 * TODO: find a shell or pseudo-shell to call
1028 * for some simple useful command
1029 */
1030
1031 return (-1);
1032}
1033
1034/*
1035 * Return TRUE if "p" contains a wildcard that can be expanded by
1036 * mch_expandpath().
1037 */
1038 int
1039mch_has_exp_wildcard(p)
1040 char_u *p;
1041{
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00001042 for ( ; *p; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001043 {
1044 if (*p == '\\' && p[1] != NUL)
1045 ++p;
1046 else if (vim_strchr((char_u *)WILDCHAR_LIST, *p) != NULL)
1047 return TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001048 }
1049 return FALSE;
1050}
1051
1052 int
1053mch_has_wildcard(p)
1054 char_u *p;
1055{
1056#ifdef USE_UNIXFILENAME
1057 if (*p == '~' && p[1] != NUL)
1058 return TRUE;
1059#endif
1060 return mch_has_exp_wildcard(p);
1061}
1062
1063
1064/*
1065 * This procedure duplicate a file, it is used in order to keep
1066 * the footprint of the previous file, when some info can be easily
1067 * restored with set_perm().
1068 *
1069 * Return -1 for failure, 0 for success.
1070 */
1071 int
1072mch_copy_file(from, to)
1073 char_u *from;
1074 char_u *to;
1075{
1076 char_u from_str[256];
1077 char_u to_str[256];
1078 char_u to_name[256];
1079
1080 HParamBlockRec paramBlock;
1081 char_u *char_ptr;
1082 int len;
1083
1084 /*
1085 * Convert C string to Pascal string
1086 */
1087 char_ptr = from;
1088 len = 1;
1089 for (; (*char_ptr != 0) && (len < 255); len++, char_ptr++)
1090 from_str[len] = *char_ptr;
1091 from_str[0] = len-1;
1092
1093 char_ptr = to;
1094 len = 1;
1095 for (; (*char_ptr != 0) && (len < 255); len++, char_ptr++)
1096 to_str[len] = *char_ptr;
1097 to_str[0] = len-1;
1098
1099 paramBlock.copyParam.ioCompletion = NULL;
1100 paramBlock.copyParam.ioNamePtr = from_str;
1101 /* paramBlock.copyParam.ioVRefnum = overided by ioFilename; */
1102 /* paramBlock.copyParam.ioDirI = overided by ioFilename; */
1103
1104 paramBlock.copyParam.ioNewName = to_str;
1105 paramBlock.copyParam.ioCopyName = to_name; /* NIL */
1106 /* paramBlock.copyParam.ioDstVRefNum = overided by ioNewName; */
1107 /* paramBlock.copyParam.ioNewDirID = overided by ioNewName; */
1108
1109
1110
1111 /*
1112 * First delete the "to" file, this is required on some systems to make
1113 * the rename() work, on other systems it makes sure that we don't have
1114 * two files when the rename() fails.
1115 */
1116 mch_remove(to);
1117
1118 /*
1119 * First try a normal rename, return if it works.
1120 */
1121 (void) PBHCopyFile(&paramBlock, false);
1122 return 0;
1123
1124}
1125
1126
1127 int
1128mch_copy_file_attribute(from, to)
1129 char_u *from;
1130 char_u *to;
1131{
Bram Moolenaar8299df92004-07-10 09:47:34 +00001132 FSSpec frFSSpec;
1133 FSSpec toFSSpec;
1134 FInfo fndrInfo;
1135 Str255 name;
1136 ResType type;
1137 ResType sink;
1138 Handle resource;
1139 short idxTypes;
1140 short nbTypes;
1141 short idxResources;
1142 short nbResources;
1143 short ID;
1144 short frRFid;
1145 short toRFid;
1146 short attrs_orig;
1147 short attrs_copy;
1148 short temp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001149
1150 /* TODO: Handle error */
Bram Moolenaar8299df92004-07-10 09:47:34 +00001151 (void)GetFSSpecFromPath(from, &frFSSpec);
1152 (void)GetFSSpecFromPath(to , &toFSSpec);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001153
1154 /* Copy resource fork */
1155 temp = 0;
1156
1157#if 1
1158 frRFid = FSpOpenResFile (&frFSSpec, fsCurPerm);
1159
1160 if (frRFid != -1)
1161 {
1162 FSpCreateResFile(&toFSSpec, 'TEXT', UNKNOWN_CREATOR, 0);
Bram Moolenaar8299df92004-07-10 09:47:34 +00001163 toRFid = FSpOpenResFile(&toFSSpec, fsRdWrPerm);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001164
Bram Moolenaar8299df92004-07-10 09:47:34 +00001165 UseResFile(frRFid);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001166
1167 nbTypes = Count1Types();
1168
1169 for (idxTypes = 1; idxTypes <= nbTypes; idxTypes++)
1170 {
Bram Moolenaar8299df92004-07-10 09:47:34 +00001171 Get1IndType(&type, idxTypes);
1172 nbResources = Count1Resources(type);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001173
Bram Moolenaar8299df92004-07-10 09:47:34 +00001174 for (idxResources = 1; idxResources <= nbResources; idxResources++)
1175 {
1176 attrs_orig = 0; /* in case GetRes fails */
1177 attrs_copy = 0; /* in case GetRes fails */
1178 resource = Get1IndResource(type, idxResources);
1179 GetResInfo(resource, &ID, &sink, name);
1180 HLock(resource);
1181 attrs_orig = GetResAttrs(resource);
1182 DetachResource(resource);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001183
1184
Bram Moolenaar8299df92004-07-10 09:47:34 +00001185 UseResFile(toRFid);
1186 AddResource(resource, type, ID, name);
1187 attrs_copy = GetResAttrs(resource);
1188 attrs_copy = (attrs_copy & 0x2) | (attrs_orig & 0xFD);
1189 SetResAttrs(resource, attrs_copy);
1190 WriteResource(resource);
1191 UpdateResFile(toRFid);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001192
Bram Moolenaar8299df92004-07-10 09:47:34 +00001193 temp = GetResAttrs(resource);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001194
Bram Moolenaar8299df92004-07-10 09:47:34 +00001195 /*SetResAttrs (resource, 0);*/
1196 HUnlock(resource);
1197 ReleaseResource(resource);
1198 UseResFile(frRFid);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001199 }
1200 }
Bram Moolenaar8299df92004-07-10 09:47:34 +00001201 CloseResFile(toRFid);
1202 CloseResFile(frRFid);
1203 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001204#endif
1205 /* Copy Finder Info */
Bram Moolenaar8299df92004-07-10 09:47:34 +00001206 (void)FSpGetFInfo(&frFSSpec, &fndrInfo);
1207 (void)FSpSetFInfo(&toFSSpec, &fndrInfo);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001208
1209 return (temp == attrs_copy);
1210}
1211
1212 int
1213mch_has_resource_fork (file)
1214 char_u *file;
1215{
1216 FSSpec fileFSSpec;
Bram Moolenaar8299df92004-07-10 09:47:34 +00001217 short fileRFid;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001218
1219 /* TODO: Handle error */
Bram Moolenaar8299df92004-07-10 09:47:34 +00001220 (void)GetFSSpecFromPath(file, &fileFSSpec);
1221 fileRFid = FSpOpenResFile(&fileFSSpec, fsCurPerm);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001222 if (fileRFid != -1)
Bram Moolenaar8299df92004-07-10 09:47:34 +00001223 CloseResFile(fileRFid);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001224
1225 return (fileRFid != -1);
1226}
1227
1228 int
1229mch_get_shellsize(void)
1230{
1231 /* never used */
1232 return OK;
1233}
1234
1235 void
1236mch_set_shellsize(void)
1237{
1238 /* never used */
1239}
1240
1241/*
1242 * Rows and/or Columns has changed.
1243 */
1244 void
1245mch_new_shellsize(void)
1246{
1247 /* never used */
1248}
1249
1250/*
1251 * Those function were set as #define before, but in order
1252 * to allow an easier us of os_unix.c for the MacOS X port,
1253 * they are change to procedure. Thec ompile whould optimize
1254 * them out.
1255 */
1256
1257 int
1258mch_can_restore_title()
1259{
1260 return TRUE;
1261}
1262
1263 int
1264mch_can_restore_icon()
1265{
1266 return TRUE;
1267}
1268
1269/*
1270 * If the machine has job control, use it to suspend the program,
1271 * otherwise fake it by starting a new shell.
1272 */
1273 void
1274mch_suspend()
1275{
1276 /* TODO: get calle in #ifndef NO_CONSOLE */
1277 gui_mch_iconify();
1278};
1279