1 /* 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_amiga.c 12 * 13 * Amiga system-dependent routines. 14 */ 15 16 #include "vim.h" 17 18 #ifdef Window 19 # undef Window /* Amiga has its own Window definition */ 20 #endif 21 22 #undef TRUE /* will be redefined by exec/types.h */ 23 #undef FALSE 24 25 /* cproto fails on missing include files, skip them */ 26 #ifndef PROTO 27 28 #ifndef LATTICE 29 # include <exec/types.h> 30 # include <exec/exec.h> 31 # include <libraries/dos.h> 32 # include <intuition/intuition.h> 33 #endif 34 35 /* XXX These are included from os_amiga.h 36 #include <proto/exec.h> 37 #include <proto/dos.h> 38 #include <proto/intuition.h> 39 */ 40 41 #include <exec/memory.h> 42 #include <libraries/dosextens.h> 43 44 #include <dos/dostags.h> /* for 2.0 functions */ 45 #include <dos/dosasl.h> 46 47 /* From version 4 of AmigaOS, several system structures must be allocated 48 * and freed using system functions. "struct AnchorPath" is one. 49 */ 50 #ifdef __amigaos4__ 51 # include <dos/anchorpath.h> 52 # define free_fib(x) FreeDosObject(DOS_FIB, x) 53 #else 54 # define free_fib(x) vim_free(fib) 55 #endif 56 57 #if defined(LATTICE) && !defined(SASC) && defined(FEAT_ARP) 58 # include <libraries/arp_pragmas.h> 59 #endif 60 61 #endif /* PROTO */ 62 63 /* 64 * At this point TRUE and FALSE are defined as 1L and 0L, but we want 1 and 0. 65 */ 66 #undef TRUE 67 #define TRUE (1) 68 #undef FALSE 69 #define FALSE (0) 70 71 #ifdef __amigaos4__ 72 # define dos_packet(a, b, c) DoPkt(a, b, c, 0, 0, 0, 0) 73 #elif !defined(AZTEC_C) && !defined(__AROS__) 74 static long dos_packet __ARGS((struct MsgPort *, long, long)); 75 #endif 76 static int lock2name __ARGS((BPTR lock, char_u *buf, long len)); 77 static void out_num __ARGS((long n)); 78 static struct FileInfoBlock *get_fib __ARGS((char_u *)); 79 static int sortcmp __ARGS((const void *a, const void *b)); 80 81 static BPTR raw_in = (BPTR)NULL; 82 static BPTR raw_out = (BPTR)NULL; 83 static int close_win = FALSE; /* set if Vim opened the window */ 84 85 #ifndef __amigaos4__ /* Use autoopen for AmigaOS4 */ 86 struct IntuitionBase *IntuitionBase = NULL; 87 #endif 88 #ifdef FEAT_ARP 89 struct ArpBase *ArpBase = NULL; 90 #endif 91 92 static struct Window *wb_window; 93 static char_u *oldwindowtitle = NULL; 94 95 #ifdef FEAT_ARP 96 int dos2 = FALSE; /* Amiga DOS 2.0x or higher */ 97 #endif 98 int size_set = FALSE; /* set to TRUE if window size was set */ 99 100 void 101 win_resize_on() 102 { 103 OUT_STR_NF("\033[12{"); 104 } 105 106 void 107 win_resize_off() 108 { 109 OUT_STR_NF("\033[12}"); 110 } 111 112 void 113 mch_write(p, len) 114 char_u *p; 115 int len; 116 { 117 Write(raw_out, (char *)p, (long)len); 118 } 119 120 /* 121 * mch_inchar(): low level input function. 122 * Get a characters from the keyboard. 123 * If time == 0 do not wait for characters. 124 * If time == n wait a short time for characters. 125 * If time == -1 wait forever for characters. 126 * 127 * Return number of characters read. 128 */ 129 int 130 mch_inchar(buf, maxlen, time, tb_change_cnt) 131 char_u *buf; 132 int maxlen; 133 long time; /* milli seconds */ 134 int tb_change_cnt; 135 { 136 int len; 137 long utime; 138 139 if (time >= 0) 140 { 141 if (time == 0) 142 utime = 100L; /* time = 0 causes problems in DOS 1.2 */ 143 else 144 utime = time * 1000L; /* convert from milli to micro secs */ 145 if (WaitForChar(raw_in, utime) == 0) /* no character available */ 146 return 0; 147 } 148 else /* time == -1 */ 149 { 150 /* 151 * If there is no character available within 2 seconds (default) 152 * write the autoscript file to disk. Or cause the CursorHold event 153 * to be triggered. 154 */ 155 if (WaitForChar(raw_in, p_ut * 1000L) == 0) 156 { 157 #ifdef FEAT_AUTOCMD 158 if (trigger_cursorhold() && maxlen >= 3) 159 { 160 buf[0] = K_SPECIAL; 161 buf[1] = KS_EXTRA; 162 buf[2] = (int)KE_CURSORHOLD; 163 return 3; 164 } 165 #endif 166 before_blocking(); 167 } 168 } 169 170 for (;;) /* repeat until we got a character */ 171 { 172 # ifdef FEAT_MBYTE 173 len = Read(raw_in, (char *)buf, (long)maxlen / input_conv.vc_factor); 174 # else 175 len = Read(raw_in, (char *)buf, (long)maxlen); 176 # endif 177 if (len > 0) 178 { 179 #ifdef FEAT_MBYTE 180 /* Convert from 'termencoding' to 'encoding'. */ 181 if (input_conv.vc_type != CONV_NONE) 182 len = convert_input(buf, len, maxlen); 183 #endif 184 return len; 185 } 186 } 187 } 188 189 /* 190 * return non-zero if a character is available 191 */ 192 int 193 mch_char_avail() 194 { 195 return (WaitForChar(raw_in, 100L) != 0); 196 } 197 198 /* 199 * Return amount of memory still available in Kbyte. 200 */ 201 long_u 202 mch_avail_mem(special) 203 int special; 204 { 205 #ifdef __amigaos4__ 206 return (long_u)AvailMem(MEMF_ANY) >> 10; 207 #else 208 return (long_u)(AvailMem(special ? (long)MEMF_CHIP : (long)MEMF_ANY)) >> 10; 209 #endif 210 } 211 212 /* 213 * Waits a specified amount of time, or until input arrives if 214 * ignoreinput is FALSE. 215 */ 216 void 217 mch_delay(msec, ignoreinput) 218 long msec; 219 int ignoreinput; 220 { 221 #ifndef LATTICE /* SAS declares void Delay(ULONG) */ 222 void Delay __ARGS((long)); 223 #endif 224 225 if (msec > 0) 226 { 227 if (ignoreinput) 228 Delay(msec / 20L); /* Delay works with 20 msec intervals */ 229 else 230 WaitForChar(raw_in, msec * 1000L); 231 } 232 } 233 234 /* 235 * We have no job control, fake it by starting a new shell. 236 */ 237 void 238 mch_suspend() 239 { 240 suspend_shell(); 241 } 242 243 #ifndef DOS_LIBRARY 244 # define DOS_LIBRARY ((UBYTE *)"dos.library") 245 #endif 246 247 void 248 mch_init() 249 { 250 static char intlibname[] = "intuition.library"; 251 252 #ifdef AZTEC_C 253 Enable_Abort = 0; /* disallow vim to be aborted */ 254 #endif 255 Columns = 80; 256 Rows = 24; 257 258 /* 259 * Set input and output channels, unless we have opened our own window 260 */ 261 if (raw_in == (BPTR)NULL) 262 { 263 raw_in = Input(); 264 raw_out = Output(); 265 /* 266 * If Input() is not interactive, then Output() will be (because of 267 * check in mch_check_win()). Used for "Vim -". 268 * Also check the other way around, for "Vim -h | more". 269 */ 270 if (!IsInteractive(raw_in)) 271 raw_in = raw_out; 272 else if (!IsInteractive(raw_out)) 273 raw_out = raw_in; 274 } 275 276 out_flush(); 277 278 wb_window = NULL; 279 #ifndef __amigaos4__ 280 if ((IntuitionBase = (struct IntuitionBase *) 281 OpenLibrary((UBYTE *)intlibname, 0L)) == NULL) 282 { 283 mch_errmsg(_("cannot open ")); 284 mch_errmsg(intlibname); 285 mch_errmsg("!?\n"); 286 mch_exit(3); 287 } 288 #endif 289 } 290 291 #ifndef PROTO 292 # include <workbench/startup.h> 293 #endif 294 295 /* 296 * Check_win checks whether we have an interactive window. 297 * If not, a new window is opened with the newcli command. 298 * If we would open a window ourselves, the :sh and :! commands would not 299 * work properly (Why? probably because we are then running in a background 300 * CLI). This also is the best way to assure proper working in a next 301 * Workbench release. 302 * 303 * For the -f option (foreground mode) we open our own window and disable :sh. 304 * Otherwise the calling program would never know when editing is finished. 305 */ 306 #define BUF2SIZE 320 /* length of buffer for argument with complete path */ 307 308 int 309 mch_check_win(argc, argv) 310 int argc; 311 char **argv; 312 { 313 int i; 314 BPTR nilfh, fh; 315 char_u buf1[24]; 316 char_u buf2[BUF2SIZE]; 317 static char_u *(constrings[3]) = {(char_u *)"con:0/0/662/210/", 318 (char_u *)"con:0/0/640/200/", 319 (char_u *)"con:0/0/320/200/"}; 320 static char_u *winerr = (char_u *)N_("VIM: Can't open window!\n"); 321 struct WBArg *argp; 322 int ac; 323 char *av; 324 char_u *device = NULL; 325 int exitval = 4; 326 #ifndef __amigaos4__ 327 struct Library *DosBase; 328 #endif 329 int usewin = FALSE; 330 331 /* 332 * check if we are running under DOS 2.0x or higher 333 */ 334 #ifndef __amigaos4__ 335 DosBase = OpenLibrary(DOS_LIBRARY, 37L); 336 if (DosBase != NULL) 337 /* if (((struct Library *)DOSBase)->lib_Version >= 37) */ 338 { 339 CloseLibrary(DosBase); 340 # ifdef FEAT_ARP 341 dos2 = TRUE; 342 # endif 343 } 344 else /* without arp functions we NEED 2.0 */ 345 { 346 # ifndef FEAT_ARP 347 mch_errmsg(_("Need Amigados version 2.04 or later\n")); 348 exit(3); 349 # else 350 /* need arp functions for dos 1.x */ 351 if (!(ArpBase = (struct ArpBase *) OpenLibrary((UBYTE *)ArpName, ArpVersion))) 352 { 353 fprintf(stderr, _("Need %s version %ld\n"), ArpName, ArpVersion); 354 exit(3); 355 } 356 # endif 357 } 358 #endif /* __amigaos4__ */ 359 360 /* 361 * scan argv[] for the "-f" and "-d" arguments 362 */ 363 for (i = 1; i < argc; ++i) 364 if (argv[i][0] == '-') 365 { 366 switch (argv[i][1]) 367 { 368 case 'f': 369 usewin = TRUE; 370 break; 371 372 case 'd': 373 if (i < argc - 1 374 #ifdef FEAT_DIFF 375 /* require using "-dev", "-d" means diff mode */ 376 && argv[i][2] == 'e' && argv[i][3] == 'v' 377 #endif 378 ) 379 device = (char_u *)argv[i + 1]; 380 break; 381 } 382 } 383 384 /* 385 * If we were not started from workbench, do not have a "-d" or "-dev" 386 * argument and we have been started with an interactive window, use that 387 * window. 388 */ 389 if (argc != 0 390 && device == NULL 391 && (IsInteractive(Input()) || IsInteractive(Output()))) 392 return OK; 393 394 /* 395 * When given the "-f" argument, we open our own window. We can't use the 396 * newcli trick below, because the calling program (mail, rn, etc.) would not 397 * know when we are finished. 398 */ 399 if (usewin) 400 { 401 /* 402 * Try to open a window. First try the specified device. 403 * Then try a 24 line 80 column window. 404 * If that fails, try two smaller ones. 405 */ 406 for (i = -1; i < 3; ++i) 407 { 408 if (i >= 0) 409 device = constrings[i]; 410 if (device != NULL && (raw_in = Open((UBYTE *)device, 411 (long)MODE_NEWFILE)) != (BPTR)NULL) 412 break; 413 } 414 if (raw_in == (BPTR)NULL) /* all three failed */ 415 { 416 mch_errmsg(_(winerr)); 417 goto exit; 418 } 419 raw_out = raw_in; 420 close_win = TRUE; 421 return OK; 422 } 423 424 if ((nilfh = Open((UBYTE *)"NIL:", (long)MODE_NEWFILE)) == (BPTR)NULL) 425 { 426 mch_errmsg(_("Cannot open NIL:\n")); 427 goto exit; 428 } 429 430 /* 431 * Make a unique name for the temp file (which we will not delete!). 432 * Use a pointer on the stack (nobody else will be using it). 433 * Under AmigaOS4, this assumption might change in the future, so 434 * we use a pointer to the current task instead. This should be a 435 * shared structure and thus globally unique. 436 */ 437 #ifdef __amigaos4__ 438 sprintf((char *)buf1, "t:nc%p", FindTask(0)); 439 #else 440 sprintf((char *)buf1, "t:nc%ld", (long)buf1); 441 #endif 442 if ((fh = Open((UBYTE *)buf1, (long)MODE_NEWFILE)) == (BPTR)NULL) 443 { 444 mch_errmsg(_("Cannot create ")); 445 mch_errmsg((char *)buf1); 446 mch_errmsg("\n"); 447 goto exit; 448 } 449 /* 450 * Write the command into the file, put quotes around the arguments that 451 * have a space in them. 452 */ 453 if (argc == 0) /* run from workbench */ 454 ac = ((struct WBStartup *)argv)->sm_NumArgs; 455 else 456 ac = argc; 457 for (i = 0; i < ac; ++i) 458 { 459 if (argc == 0) 460 { 461 *buf2 = NUL; 462 argp = &(((struct WBStartup *)argv)->sm_ArgList[i]); 463 if (argp->wa_Lock) 464 (void)lock2name(argp->wa_Lock, buf2, (long)(BUF2SIZE - 1)); 465 #ifdef FEAT_ARP 466 if (dos2) /* use 2.0 function */ 467 #endif 468 AddPart((UBYTE *)buf2, (UBYTE *)argp->wa_Name, (long)(BUF2SIZE - 1)); 469 #ifdef FEAT_ARP 470 else /* use arp function */ 471 TackOn((char *)buf2, argp->wa_Name); 472 #endif 473 av = (char *)buf2; 474 } 475 else 476 av = argv[i]; 477 478 /* skip '-d' or "-dev" option */ 479 if (av[0] == '-' && av[1] == 'd' 480 #ifdef FEAT_DIFF 481 && av[2] == 'e' && av[3] == 'v' 482 #endif 483 ) 484 { 485 ++i; 486 continue; 487 } 488 if (vim_strchr((char_u *)av, ' ')) 489 Write(fh, "\"", 1L); 490 Write(fh, av, (long)strlen(av)); 491 if (vim_strchr((char_u *)av, ' ')) 492 Write(fh, "\"", 1L); 493 Write(fh, " ", 1L); 494 } 495 Write(fh, "\nendcli\n", 8L); 496 Close(fh); 497 498 /* 499 * Try to open a new cli in a window. If "-d" or "-dev" argument was given try 500 * to open the specified device. Then try a 24 line 80 column window. If that 501 * fails, try two smaller ones. 502 */ 503 for (i = -1; i < 3; ++i) 504 { 505 if (i >= 0) 506 device = constrings[i]; 507 else if (device == NULL) 508 continue; 509 sprintf((char *)buf2, "newcli <nil: >nil: %s from %s", (char *)device, (char *)buf1); 510 #ifdef FEAT_ARP 511 if (dos2) 512 { 513 #endif 514 if (!SystemTags((UBYTE *)buf2, SYS_UserShell, TRUE, TAG_DONE)) 515 break; 516 #ifdef FEAT_ARP 517 } 518 else 519 { 520 if (Execute((UBYTE *)buf2, nilfh, nilfh)) 521 break; 522 } 523 #endif 524 } 525 if (i == 3) /* all three failed */ 526 { 527 DeleteFile((UBYTE *)buf1); 528 mch_errmsg(_(winerr)); 529 goto exit; 530 } 531 exitval = 0; /* The Execute succeeded: exit this program */ 532 533 exit: 534 #ifdef FEAT_ARP 535 if (ArpBase) 536 CloseLibrary((struct Library *) ArpBase); 537 #endif 538 exit(exitval); 539 /* NOTREACHED */ 540 return FAIL; 541 } 542 543 /* 544 * Return TRUE if the input comes from a terminal, FALSE otherwise. 545 * We fake there is a window, because we can always open one! 546 */ 547 int 548 mch_input_isatty() 549 { 550 return TRUE; 551 } 552 553 /* 554 * fname_case(): Set the case of the file name, if it already exists. 555 * This will cause the file name to remain exactly the same 556 * if the file system ignores, but preserves case. 557 */ 558 /*ARGSUSED*/ 559 void 560 fname_case(name, len) 561 char_u *name; 562 int len; /* buffer size, ignored here */ 563 { 564 struct FileInfoBlock *fib; 565 size_t flen; 566 567 fib = get_fib(name); 568 if (fib != NULL) 569 { 570 flen = STRLEN(name); 571 /* TODO: Check if this fix applies to AmigaOS < 4 too.*/ 572 #ifdef __amigaos4__ 573 if (fib->fib_DirEntryType == ST_ROOT) 574 strcat(fib->fib_FileName, ":"); 575 #endif 576 if (flen == strlen(fib->fib_FileName)) /* safety check */ 577 mch_memmove(name, fib->fib_FileName, flen); 578 free_fib(fib); 579 } 580 } 581 582 /* 583 * Get the FileInfoBlock for file "fname" 584 * The returned structure has to be free()d. 585 * Returns NULL on error. 586 */ 587 static struct FileInfoBlock * 588 get_fib(fname) 589 char_u *fname; 590 { 591 BPTR flock; 592 struct FileInfoBlock *fib; 593 594 if (fname == NULL) /* safety check */ 595 return NULL; 596 #ifdef __amigaos4__ 597 fib = AllocDosObject(DOS_FIB,0); 598 #else 599 fib = (struct FileInfoBlock *)alloc(sizeof(struct FileInfoBlock)); 600 #endif 601 if (fib != NULL) 602 { 603 flock = Lock((UBYTE *)fname, (long)ACCESS_READ); 604 if (flock == (BPTR)NULL || !Examine(flock, fib)) 605 { 606 free_fib(fib); /* in case of an error the memory is freed here */ 607 fib = NULL; 608 } 609 if (flock) 610 UnLock(flock); 611 } 612 return fib; 613 } 614 615 #ifdef FEAT_TITLE 616 /* 617 * set the title of our window 618 * icon name is not set 619 */ 620 void 621 mch_settitle(title, icon) 622 char_u *title; 623 char_u *icon; 624 { 625 if (wb_window != NULL && title != NULL) 626 SetWindowTitles(wb_window, (UBYTE *)title, (UBYTE *)-1L); 627 } 628 629 /* 630 * Restore the window/icon title. 631 * which is one of: 632 * 1 Just restore title 633 * 2 Just restore icon (which we don't have) 634 * 3 Restore title and icon (which we don't have) 635 */ 636 void 637 mch_restore_title(which) 638 int which; 639 { 640 if (which & 1) 641 mch_settitle(oldwindowtitle, NULL); 642 } 643 644 int 645 mch_can_restore_title() 646 { 647 return (wb_window != NULL); 648 } 649 650 int 651 mch_can_restore_icon() 652 { 653 return FALSE; 654 } 655 #endif 656 657 /* 658 * Insert user name in s[len]. 659 */ 660 int 661 mch_get_user_name(s, len) 662 char_u *s; 663 int len; 664 { 665 /* TODO: Implement this. */ 666 *s = NUL; 667 return FAIL; 668 } 669 670 /* 671 * Insert host name is s[len]. 672 */ 673 void 674 mch_get_host_name(s, len) 675 char_u *s; 676 int len; 677 { 678 #if defined(__amigaos4__) && defined(__CLIB2__) 679 gethostname(s, len); 680 #else 681 vim_strncpy(s, "Amiga", len - 1); 682 #endif 683 } 684 685 /* 686 * return process ID 687 */ 688 long 689 mch_get_pid() 690 { 691 #ifdef __amigaos4__ 692 /* This is as close to a pid as we can come. We could use CLI numbers also, 693 * but then we would have two different types of process identifiers. 694 */ 695 return((long)FindTask(0)); 696 #else 697 return (long)0; 698 #endif 699 } 700 701 /* 702 * Get name of current directory into buffer 'buf' of length 'len' bytes. 703 * Return OK for success, FAIL for failure. 704 */ 705 int 706 mch_dirname(buf, len) 707 char_u *buf; 708 int len; 709 { 710 return mch_FullName((char_u *)"", buf, len, FALSE); 711 } 712 713 /* 714 * get absolute file name into buffer 'buf' of length 'len' bytes 715 * 716 * return FAIL for failure, OK otherwise 717 */ 718 int 719 mch_FullName(fname, buf, len, force) 720 char_u *fname, *buf; 721 int len; 722 int force; 723 { 724 BPTR l; 725 int retval = FAIL; 726 int i; 727 728 /* Lock the file. If it exists, we can get the exact name. */ 729 if ((l = Lock((UBYTE *)fname, (long)ACCESS_READ)) != (BPTR)0) 730 { 731 retval = lock2name(l, buf, (long)len - 1); 732 UnLock(l); 733 } 734 else if (force || !mch_isFullName(fname)) /* not a full path yet */ 735 { 736 /* 737 * If the file cannot be locked (doesn't exist), try to lock the 738 * current directory and concatenate the file name. 739 */ 740 if ((l = Lock((UBYTE *)"", (long)ACCESS_READ)) != (BPTR)NULL) 741 { 742 retval = lock2name(l, buf, (long)len); 743 UnLock(l); 744 if (retval == OK) 745 { 746 i = STRLEN(buf); 747 /* Concatenate the fname to the directory. Don't add a slash 748 * if fname is empty, but do change "" to "/". */ 749 if (i == 0 || *fname != NUL) 750 { 751 if (i < len - 1 && (i == 0 || buf[i - 1] != ':')) 752 buf[i++] = '/'; 753 vim_strncpy(buf + i, fname, len - i - 1); 754 } 755 } 756 } 757 } 758 if (*buf == 0 || *buf == ':') 759 retval = FAIL; /* something failed; use the file name */ 760 return retval; 761 } 762 763 /* 764 * Return TRUE if "fname" does not depend on the current directory. 765 */ 766 int 767 mch_isFullName(fname) 768 char_u *fname; 769 { 770 return (vim_strchr(fname, ':') != NULL && *fname != ':'); 771 } 772 773 /* 774 * Get the full file name from a lock. Use 2.0 function if possible, because 775 * the arp function has more restrictions on the path length. 776 * 777 * return FAIL for failure, OK otherwise 778 */ 779 static int 780 lock2name(lock, buf, len) 781 BPTR lock; 782 char_u *buf; 783 long len; 784 { 785 #ifdef FEAT_ARP 786 if (dos2) /* use 2.0 function */ 787 #endif 788 return ((int)NameFromLock(lock, (UBYTE *)buf, len) ? OK : FAIL); 789 #ifdef FEAT_ARP 790 else /* use arp function */ 791 return ((int)PathName(lock, (char *)buf, (long)(len/32)) ? OK : FAIL); 792 #endif 793 } 794 795 /* 796 * get file permissions for 'name' 797 * Returns -1 when it doesn't exist. 798 */ 799 long 800 mch_getperm(name) 801 char_u *name; 802 { 803 struct FileInfoBlock *fib; 804 long retval = -1; 805 806 fib = get_fib(name); 807 if (fib != NULL) 808 { 809 retval = fib->fib_Protection; 810 free_fib(fib); 811 } 812 return retval; 813 } 814 815 /* 816 * set file permission for 'name' to 'perm' 817 * 818 * return FAIL for failure, OK otherwise 819 */ 820 int 821 mch_setperm(name, perm) 822 char_u *name; 823 long perm; 824 { 825 perm &= ~FIBF_ARCHIVE; /* reset archived bit */ 826 return (SetProtection((UBYTE *)name, (long)perm) ? OK : FAIL); 827 } 828 829 /* 830 * Set hidden flag for "name". 831 */ 832 void 833 mch_hide(name) 834 char_u *name; 835 { 836 /* can't hide a file */ 837 } 838 839 /* 840 * return FALSE if "name" is not a directory 841 * return TRUE if "name" is a directory. 842 * return FALSE for error. 843 */ 844 int 845 mch_isdir(name) 846 char_u *name; 847 { 848 struct FileInfoBlock *fib; 849 int retval = FALSE; 850 851 fib = get_fib(name); 852 if (fib != NULL) 853 { 854 #ifdef __amigaos4__ 855 retval = (FIB_IS_DRAWER(fib)) ? TRUE : FALSE; 856 #else 857 retval = ((fib->fib_DirEntryType >= 0) ? TRUE : FALSE); 858 #endif 859 free_fib(fib); 860 } 861 return retval; 862 } 863 864 /* 865 * Create directory "name". 866 */ 867 int 868 mch_mkdir(name) 869 char_u *name; 870 { 871 BPTR lock; 872 873 lock = CreateDir(name); 874 if (lock != NULL) 875 { 876 UnLock(lock); 877 return 0; 878 } 879 return -1; 880 } 881 882 /* 883 * Return 1 if "name" can be executed, 0 if not. 884 * If "use_path" is FALSE only check if "name" is executable. 885 * Return -1 if unknown. 886 */ 887 int 888 mch_can_exe(name, path, use_path) 889 char_u *name; 890 char_u **path; 891 int use_path; 892 { 893 /* TODO */ 894 return -1; 895 } 896 897 /* 898 * Check what "name" is: 899 * NODE_NORMAL: file or directory (or doesn't exist) 900 * NODE_WRITABLE: writable device, socket, fifo, etc. 901 * NODE_OTHER: non-writable things 902 */ 903 int 904 mch_nodetype(name) 905 char_u *name; 906 { 907 /* TODO */ 908 return NODE_NORMAL; 909 } 910 911 void 912 mch_early_init() 913 { 914 } 915 916 /* 917 * Careful: mch_exit() may be called before mch_init()! 918 */ 919 void 920 mch_exit(r) 921 int r; 922 { 923 if (raw_in) /* put terminal in 'normal' mode */ 924 { 925 settmode(TMODE_COOK); 926 stoptermcap(); 927 } 928 out_char('\n'); 929 if (raw_out) 930 { 931 if (term_console) 932 { 933 win_resize_off(); /* window resize events de-activated */ 934 if (size_set) 935 OUT_STR("\233t\233u"); /* reset window size (CSI t CSI u) */ 936 } 937 out_flush(); 938 } 939 940 #ifdef FEAT_TITLE 941 mch_restore_title(3); /* restore window title */ 942 #endif 943 944 ml_close_all(TRUE); /* remove all memfiles */ 945 946 #ifdef FEAT_ARP 947 if (ArpBase) 948 CloseLibrary((struct Library *) ArpBase); 949 #endif 950 if (close_win) 951 Close(raw_in); 952 if (r) 953 printf(_("Vim exiting with %d\n"), r); /* somehow this makes :cq work!? */ 954 exit(r); 955 } 956 957 /* 958 * This is a routine for setting a given stream to raw or cooked mode on the 959 * Amiga . This is useful when you are using Lattice C to produce programs 960 * that want to read single characters with the "getch()" or "fgetc" call. 961 * 962 * Written : 18-Jun-87 By Chuck McManis. 963 */ 964 965 #define MP(xx) ((struct MsgPort *)((struct FileHandle *) (BADDR(xx)))->fh_Type) 966 967 /* 968 * Function mch_settmode() - Convert the specified file pointer to 'raw' or 969 * 'cooked' mode. This only works on TTY's. 970 * 971 * Raw: keeps DOS from translating keys for you, also (BIG WIN) it means 972 * getch() will return immediately rather than wait for a return. You 973 * lose editing features though. 974 * 975 * Cooked: This function returns the designate file pointer to it's normal, 976 * wait for a <CR> mode. This is exactly like raw() except that 977 * it sends a 0 to the console to make it back into a CON: from a RAW: 978 */ 979 void 980 mch_settmode(tmode) 981 int tmode; 982 { 983 #if defined(__AROS__) || defined(__amigaos4__) 984 if (!SetMode(raw_in, tmode == TMODE_RAW ? 1 : 0)) 985 #else 986 if (dos_packet(MP(raw_in), (long)ACTION_SCREEN_MODE, 987 tmode == TMODE_RAW ? -1L : 0L) == 0) 988 #endif 989 mch_errmsg(_("cannot change console mode ?!\n")); 990 } 991 992 /* 993 * set screen mode, always fails. 994 */ 995 int 996 mch_screenmode(arg) 997 char_u *arg; 998 { 999 EMSG(_(e_screenmode)); 1000 return FAIL; 1001 } 1002 1003 /* 1004 * Code for this routine came from the following : 1005 * 1006 * ConPackets.c - C. Scheppner, A. Finkel, P. Lindsay CBM 1007 * DOS packet example 1008 * Requires 1.2 1009 * 1010 * Found on Fish Disk 56. 1011 * 1012 * Heavely modified by mool. 1013 */ 1014 1015 #ifndef PROTO 1016 # include <devices/conunit.h> 1017 #endif 1018 1019 /* 1020 * try to get the real window size 1021 * return FAIL for failure, OK otherwise 1022 */ 1023 int 1024 mch_get_shellsize() 1025 { 1026 struct ConUnit *conUnit; 1027 #ifndef __amigaos4__ 1028 char id_a[sizeof(struct InfoData) + 3]; 1029 #endif 1030 struct InfoData *id=0; 1031 1032 if (!term_console) /* not an amiga window */ 1033 goto out; 1034 1035 /* insure longword alignment */ 1036 #ifdef __amigaos4__ 1037 if (!(id = AllocDosObject(DOS_INFODATA, 0))) 1038 goto out; 1039 #else 1040 id = (struct InfoData *)(((long)id_a + 3L) & ~3L); 1041 #endif 1042 1043 /* 1044 * Should make console aware of real window size, not the one we set. 1045 * Unfortunately, under DOS 2.0x this redraws the window and it 1046 * is rarely needed, so we skip it now, unless we changed the size. 1047 */ 1048 if (size_set) 1049 OUT_STR("\233t\233u"); /* CSI t CSI u */ 1050 out_flush(); 1051 1052 #ifdef __AROS__ 1053 if (!Info(raw_out, id) 1054 || (wb_window = (struct Window *) id->id_VolumeNode) == NULL) 1055 #else 1056 if (dos_packet(MP(raw_out), (long)ACTION_DISK_INFO, ((ULONG) id) >> 2) == 0 1057 || (wb_window = (struct Window *)id->id_VolumeNode) == NULL) 1058 #endif 1059 { 1060 /* it's not an amiga window, maybe aux device */ 1061 /* terminal type should be set */ 1062 term_console = FALSE; 1063 goto out; 1064 } 1065 if (oldwindowtitle == NULL) 1066 oldwindowtitle = (char_u *)wb_window->Title; 1067 if (id->id_InUse == (BPTR)NULL) 1068 { 1069 mch_errmsg(_("mch_get_shellsize: not a console??\n")); 1070 return FAIL; 1071 } 1072 conUnit = (struct ConUnit *) ((struct IOStdReq *) id->id_InUse)->io_Unit; 1073 1074 /* get window size */ 1075 Rows = conUnit->cu_YMax + 1; 1076 Columns = conUnit->cu_XMax + 1; 1077 if (Rows < 0 || Rows > 200) /* cannot be an amiga window */ 1078 { 1079 Columns = 80; 1080 Rows = 24; 1081 term_console = FALSE; 1082 return FAIL; 1083 } 1084 1085 return OK; 1086 out: 1087 #ifdef __amigaos4__ 1088 FreeDosObject(DOS_INFODATA, id); /* Safe to pass NULL */ 1089 #endif 1090 1091 return FAIL; 1092 } 1093 1094 /* 1095 * Try to set the real window size to Rows and Columns. 1096 */ 1097 void 1098 mch_set_shellsize() 1099 { 1100 if (term_console) 1101 { 1102 size_set = TRUE; 1103 out_char(CSI); 1104 out_num((long)Rows); 1105 out_char('t'); 1106 out_char(CSI); 1107 out_num((long)Columns); 1108 out_char('u'); 1109 out_flush(); 1110 } 1111 } 1112 1113 /* 1114 * Rows and/or Columns has changed. 1115 */ 1116 void 1117 mch_new_shellsize() 1118 { 1119 /* Nothing to do. */ 1120 } 1121 1122 /* 1123 * out_num - output a (big) number fast 1124 */ 1125 static void 1126 out_num(n) 1127 long n; 1128 { 1129 OUT_STR_NF(tltoa((unsigned long)n)); 1130 } 1131 1132 #if !defined(AZTEC_C) && !defined(__AROS__) && !defined(__amigaos4__) 1133 /* 1134 * Sendpacket.c 1135 * 1136 * An invaluable addition to your Amiga.lib file. This code sends a packet to 1137 * the given message port. This makes working around DOS lots easier. 1138 * 1139 * Note, I didn't write this, those wonderful folks at CBM did. I do suggest 1140 * however that you may wish to add it to Amiga.Lib, to do so, compile it and 1141 * say 'oml lib:amiga.lib -r sendpacket.o' 1142 */ 1143 1144 #ifndef PROTO 1145 /* #include <proto/exec.h> */ 1146 /* #include <proto/dos.h> */ 1147 # include <exec/memory.h> 1148 #endif 1149 1150 /* 1151 * Function - dos_packet written by Phil Lindsay, Carolyn Scheppner, and Andy 1152 * Finkel. This function will send a packet of the given type to the Message 1153 * Port supplied. 1154 */ 1155 1156 static long 1157 dos_packet(pid, action, arg) 1158 struct MsgPort *pid; /* process identifier ... (handlers message port) */ 1159 long action, /* packet type ... (what you want handler to do) */ 1160 arg; /* single argument */ 1161 { 1162 # ifdef FEAT_ARP 1163 struct MsgPort *replyport; 1164 struct StandardPacket *packet; 1165 long res1; 1166 1167 if (dos2) 1168 # endif 1169 return DoPkt(pid, action, arg, 0L, 0L, 0L, 0L); /* use 2.0 function */ 1170 # ifdef FEAT_ARP 1171 1172 replyport = (struct MsgPort *) CreatePort(NULL, 0); /* use arp function */ 1173 if (!replyport) 1174 return (0); 1175 1176 /* Allocate space for a packet, make it public and clear it */ 1177 packet = (struct StandardPacket *) 1178 AllocMem((long) sizeof(struct StandardPacket), MEMF_PUBLIC | MEMF_CLEAR); 1179 if (!packet) { 1180 DeletePort(replyport); 1181 return (0); 1182 } 1183 packet->sp_Msg.mn_Node.ln_Name = (char *) &(packet->sp_Pkt); 1184 packet->sp_Pkt.dp_Link = &(packet->sp_Msg); 1185 packet->sp_Pkt.dp_Port = replyport; 1186 packet->sp_Pkt.dp_Type = action; 1187 packet->sp_Pkt.dp_Arg1 = arg; 1188 1189 PutMsg(pid, (struct Message *)packet); /* send packet */ 1190 1191 WaitPort(replyport); 1192 GetMsg(replyport); 1193 1194 res1 = packet->sp_Pkt.dp_Res1; 1195 1196 FreeMem(packet, (long) sizeof(struct StandardPacket)); 1197 DeletePort(replyport); 1198 1199 return (res1); 1200 # endif 1201 } 1202 #endif /* !defined(AZTEC_C) && !defined(__AROS__) */ 1203 1204 /* 1205 * Call shell. 1206 * Return error number for failure, 0 otherwise 1207 */ 1208 int 1209 mch_call_shell(cmd, options) 1210 char_u *cmd; 1211 int options; /* SHELL_*, see vim.h */ 1212 { 1213 BPTR mydir; 1214 int x; 1215 int tmode = cur_tmode; 1216 #ifdef AZTEC_C 1217 int use_execute; 1218 char_u *shellcmd = NULL; 1219 char_u *shellarg; 1220 #endif 1221 int retval = 0; 1222 1223 if (close_win) 1224 { 1225 /* if Vim opened a window: Executing a shell may cause crashes */ 1226 EMSG(_("E360: Cannot execute shell with -f option")); 1227 return -1; 1228 } 1229 1230 if (term_console) 1231 win_resize_off(); /* window resize events de-activated */ 1232 out_flush(); 1233 1234 if (options & SHELL_COOKED) 1235 settmode(TMODE_COOK); /* set to normal mode */ 1236 mydir = Lock((UBYTE *)"", (long)ACCESS_READ); /* remember current dir */ 1237 1238 #if !defined(AZTEC_C) /* not tested very much */ 1239 if (cmd == NULL) 1240 { 1241 # ifdef FEAT_ARP 1242 if (dos2) 1243 # endif 1244 x = SystemTags(p_sh, SYS_UserShell, TRUE, TAG_DONE); 1245 # ifdef FEAT_ARP 1246 else 1247 x = Execute(p_sh, raw_in, raw_out); 1248 # endif 1249 } 1250 else 1251 { 1252 # ifdef FEAT_ARP 1253 if (dos2) 1254 # endif 1255 x = SystemTags((char *)cmd, SYS_UserShell, TRUE, TAG_DONE); 1256 # ifdef FEAT_ARP 1257 else 1258 x = Execute((char *)cmd, 0L, raw_out); 1259 # endif 1260 } 1261 # ifdef FEAT_ARP 1262 if ((dos2 && x < 0) || (!dos2 && !x)) 1263 # else 1264 if (x < 0) 1265 # endif 1266 { 1267 MSG_PUTS(_("Cannot execute ")); 1268 if (cmd == NULL) 1269 { 1270 MSG_PUTS(_("shell ")); 1271 msg_outtrans(p_sh); 1272 } 1273 else 1274 msg_outtrans(cmd); 1275 msg_putchar('\n'); 1276 retval = -1; 1277 } 1278 # ifdef FEAT_ARP 1279 else if (!dos2 || x) 1280 # else 1281 else if (x) 1282 # endif 1283 { 1284 if ((x = IoErr()) != 0) 1285 { 1286 if (!(options & SHELL_SILENT)) 1287 { 1288 msg_putchar('\n'); 1289 msg_outnum((long)x); 1290 MSG_PUTS(_(" returned\n")); 1291 } 1292 retval = x; 1293 } 1294 } 1295 #else /* else part is for AZTEC_C */ 1296 if (p_st >= 4 || (p_st >= 2 && !(options & SHELL_FILTER))) 1297 use_execute = 1; 1298 else 1299 use_execute = 0; 1300 if (!use_execute) 1301 { 1302 /* 1303 * separate shell name from argument 1304 */ 1305 shellcmd = vim_strsave(p_sh); 1306 if (shellcmd == NULL) /* out of memory, use Execute */ 1307 use_execute = 1; 1308 else 1309 { 1310 shellarg = skiptowhite(shellcmd); /* find start of arguments */ 1311 if (*shellarg != NUL) 1312 { 1313 *shellarg++ = NUL; 1314 shellarg = skipwhite(shellarg); 1315 } 1316 } 1317 } 1318 if (cmd == NULL) 1319 { 1320 if (use_execute) 1321 { 1322 # ifdef FEAT_ARP 1323 if (dos2) 1324 # endif 1325 x = SystemTags((UBYTE *)p_sh, SYS_UserShell, TRUE, TAG_DONE); 1326 # ifdef FEAT_ARP 1327 else 1328 x = !Execute((UBYTE *)p_sh, raw_in, raw_out); 1329 # endif 1330 } 1331 else 1332 x = fexecl((char *)shellcmd, (char *)shellcmd, (char *)shellarg, NULL); 1333 } 1334 else if (use_execute) 1335 { 1336 # ifdef FEAT_ARP 1337 if (dos2) 1338 # endif 1339 x = SystemTags((UBYTE *)cmd, SYS_UserShell, TRUE, TAG_DONE); 1340 # ifdef FEAT_ARP 1341 else 1342 x = !Execute((UBYTE *)cmd, 0L, raw_out); 1343 # endif 1344 } 1345 else if (p_st & 1) 1346 x = fexecl((char *)shellcmd, (char *)shellcmd, (char *)shellarg, 1347 (char *)cmd, NULL); 1348 else 1349 x = fexecl((char *)shellcmd, (char *)shellcmd, (char *)shellarg, 1350 (char *)p_shcf, (char *)cmd, NULL); 1351 # ifdef FEAT_ARP 1352 if ((dos2 && x < 0) || (!dos2 && x)) 1353 # else 1354 if (x < 0) 1355 # endif 1356 { 1357 MSG_PUTS(_("Cannot execute ")); 1358 if (use_execute) 1359 { 1360 if (cmd == NULL) 1361 msg_outtrans(p_sh); 1362 else 1363 msg_outtrans(cmd); 1364 } 1365 else 1366 { 1367 MSG_PUTS(_("shell ")); 1368 msg_outtrans(shellcmd); 1369 } 1370 msg_putchar('\n'); 1371 retval = -1; 1372 } 1373 else 1374 { 1375 if (use_execute) 1376 { 1377 # ifdef FEAT_ARP 1378 if (!dos2 || x) 1379 # else 1380 if (x) 1381 # endif 1382 x = IoErr(); 1383 } 1384 else 1385 x = wait(); 1386 if (x) 1387 { 1388 if (!(options & SHELL_SILENT) && !emsg_silent) 1389 { 1390 msg_putchar('\n'); 1391 msg_outnum((long)x); 1392 MSG_PUTS(_(" returned\n")); 1393 } 1394 retval = x; 1395 } 1396 } 1397 vim_free(shellcmd); 1398 #endif /* AZTEC_C */ 1399 1400 if ((mydir = CurrentDir(mydir)) != 0) /* make sure we stay in the same directory */ 1401 UnLock(mydir); 1402 if (tmode == TMODE_RAW) 1403 settmode(TMODE_RAW); /* set to raw mode */ 1404 #ifdef FEAT_TITLE 1405 resettitle(); 1406 #endif 1407 if (term_console) 1408 win_resize_on(); /* window resize events activated */ 1409 return retval; 1410 } 1411 1412 /* 1413 * check for an "interrupt signal" 1414 * We only react to a CTRL-C, but also clear the other break signals to avoid 1415 * trouble with lattice-c programs. 1416 */ 1417 void 1418 mch_breakcheck() 1419 { 1420 if (SetSignal(0L, (long)(SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D|SIGBREAKF_CTRL_E|SIGBREAKF_CTRL_F)) & SIGBREAKF_CTRL_C) 1421 got_int = TRUE; 1422 } 1423 1424 /* this routine causes manx to use this Chk_Abort() rather than it's own */ 1425 /* otherwise it resets our ^C when doing any I/O (even when Enable_Abort */ 1426 /* is zero). Since we want to check for our own ^C's */ 1427 1428 #ifdef _DCC 1429 #define Chk_Abort chkabort 1430 #endif 1431 1432 #ifdef LATTICE 1433 void __regargs __chkabort(void); 1434 1435 void __regargs __chkabort(void) 1436 {} 1437 1438 #else 1439 long 1440 Chk_Abort(void) 1441 { 1442 return(0L); 1443 } 1444 #endif 1445 1446 /* 1447 * mch_expandpath() - this code does wild-card pattern matching using the arp 1448 * routines. 1449 * 1450 * "pat" has backslashes before chars that are not to be expanded. 1451 * Returns the number of matches found. 1452 * 1453 * This is based on WildDemo2.c (found in arp1.1 distribution). 1454 * That code's copyright follows: 1455 * Copyright (c) 1987, Scott Ballantyne 1456 * Use and abuse as you please. 1457 */ 1458 1459 #ifdef __amigaos4__ 1460 # define ANCHOR_BUF_SIZE 1024 1461 #else 1462 # define ANCHOR_BUF_SIZE (512) 1463 # define ANCHOR_SIZE (sizeof(struct AnchorPath) + ANCHOR_BUF_SIZE) 1464 #endif 1465 1466 int 1467 mch_expandpath(gap, pat, flags) 1468 garray_T *gap; 1469 char_u *pat; 1470 int flags; /* EW_* flags */ 1471 { 1472 struct AnchorPath *Anchor; 1473 LONG Result; 1474 char_u *starbuf, *sp, *dp; 1475 int start_len; 1476 int matches; 1477 #ifdef __amigaos4__ 1478 struct TagItem AnchorTags[] = { 1479 {ADO_Strlen, ANCHOR_BUF_SIZE}, 1480 {ADO_Flags, APF_DODOT|APF_DOWILD|APF_MultiAssigns}, 1481 {TAG_DONE, 0L} 1482 }; 1483 #endif 1484 1485 start_len = gap->ga_len; 1486 1487 /* Get our AnchorBase */ 1488 #ifdef __amigaos4__ 1489 Anchor = AllocDosObject(DOS_ANCHORPATH, AnchorTags); 1490 #else 1491 Anchor = (struct AnchorPath *)alloc_clear((unsigned)ANCHOR_SIZE); 1492 #endif 1493 if (Anchor == NULL) 1494 return 0; 1495 1496 #ifndef __amigaos4__ 1497 Anchor->ap_Strlen = ANCHOR_BUF_SIZE; /* ap_Length not supported anymore */ 1498 # ifdef APF_DODOT 1499 Anchor->ap_Flags = APF_DODOT | APF_DOWILD; /* allow '.' for current dir */ 1500 # else 1501 Anchor->ap_Flags = APF_DoDot | APF_DoWild; /* allow '.' for current dir */ 1502 # endif 1503 #endif 1504 1505 #ifdef FEAT_ARP 1506 if (dos2) 1507 { 1508 #endif 1509 /* hack to replace '*' by '#?' */ 1510 starbuf = alloc((unsigned)(2 * STRLEN(pat) + 1)); 1511 if (starbuf == NULL) 1512 goto Return; 1513 for (sp = pat, dp = starbuf; *sp; ++sp) 1514 { 1515 if (*sp == '*') 1516 { 1517 *dp++ = '#'; 1518 *dp++ = '?'; 1519 } 1520 else 1521 *dp++ = *sp; 1522 } 1523 *dp = NUL; 1524 Result = MatchFirst((UBYTE *)starbuf, Anchor); 1525 vim_free(starbuf); 1526 #ifdef FEAT_ARP 1527 } 1528 else 1529 Result = FindFirst((char *)pat, Anchor); 1530 #endif 1531 1532 /* 1533 * Loop to get all matches. 1534 */ 1535 while (Result == 0) 1536 { 1537 #ifdef __amigaos4__ 1538 addfile(gap, (char_u *)Anchor->ap_Buffer, flags); 1539 #else 1540 addfile(gap, (char_u *)Anchor->ap_Buf, flags); 1541 #endif 1542 #ifdef FEAT_ARP 1543 if (dos2) 1544 #endif 1545 Result = MatchNext(Anchor); 1546 #ifdef FEAT_ARP 1547 else 1548 Result = FindNext(Anchor); 1549 #endif 1550 } 1551 matches = gap->ga_len - start_len; 1552 1553 if (Result == ERROR_BUFFER_OVERFLOW) 1554 EMSG(_("ANCHOR_BUF_SIZE too small.")); 1555 else if (matches == 0 && Result != ERROR_OBJECT_NOT_FOUND 1556 && Result != ERROR_DEVICE_NOT_MOUNTED 1557 && Result != ERROR_NO_MORE_ENTRIES) 1558 EMSG(_("I/O ERROR")); 1559 1560 /* 1561 * Sort the files for this pattern. 1562 */ 1563 if (matches) 1564 qsort((void *)(((char_u **)gap->ga_data) + start_len), 1565 (size_t)matches, sizeof(char_u *), sortcmp); 1566 1567 /* Free the wildcard stuff */ 1568 #ifdef FEAT_ARP 1569 if (dos2) 1570 #endif 1571 MatchEnd(Anchor); 1572 #ifdef FEAT_ARP 1573 else 1574 FreeAnchorChain(Anchor); 1575 #endif 1576 1577 Return: 1578 #ifdef __amigaos4__ 1579 FreeDosObject(DOS_ANCHORPATH, Anchor); 1580 #else 1581 vim_free(Anchor); 1582 #endif 1583 1584 return matches; 1585 } 1586 1587 static int 1588 sortcmp(a, b) 1589 const void *a, *b; 1590 { 1591 char *s = *(char **)a; 1592 char *t = *(char **)b; 1593 1594 return pathcmp(s, t, -1); 1595 } 1596 1597 /* 1598 * Return TRUE if "p" has wildcards that can be expanded by mch_expandpath(). 1599 */ 1600 int 1601 mch_has_exp_wildcard(p) 1602 char_u *p; 1603 { 1604 for ( ; *p; mb_ptr_adv(p)) 1605 { 1606 if (*p == '\\' && p[1] != NUL) 1607 ++p; 1608 else if (vim_strchr((char_u *)"*?[(#", *p) != NULL) 1609 return TRUE; 1610 } 1611 return FALSE; 1612 } 1613 1614 int 1615 mch_has_wildcard(p) 1616 char_u *p; 1617 { 1618 for ( ; *p; mb_ptr_adv(p)) 1619 { 1620 if (*p == '\\' && p[1] != NUL) 1621 ++p; 1622 else 1623 if (vim_strchr((char_u *) 1624 # ifdef VIM_BACKTICK 1625 "*?[(#$`" 1626 # else 1627 "*?[(#$" 1628 # endif 1629 , *p) != NULL 1630 || (*p == '~' && p[1] != NUL)) 1631 return TRUE; 1632 } 1633 return FALSE; 1634 } 1635 1636 /* 1637 * With AmigaDOS 2.0 support for reading local environment variables 1638 * 1639 * Two buffers are allocated: 1640 * - A big one to do the expansion into. It is freed before returning. 1641 * - A small one to hold the return value. It is kept until the next call. 1642 */ 1643 char_u * 1644 mch_getenv(var) 1645 char_u *var; 1646 { 1647 int len; 1648 UBYTE *buf; /* buffer to expand in */ 1649 char_u *retval; /* return value */ 1650 static char_u *alloced = NULL; /* allocated memory */ 1651 1652 #ifdef FEAT_ARP 1653 if (!dos2) 1654 retval = (char_u *)getenv((char *)var); 1655 else 1656 #endif 1657 { 1658 vim_free(alloced); 1659 alloced = NULL; 1660 retval = NULL; 1661 1662 buf = alloc(IOSIZE); 1663 if (buf == NULL) 1664 return NULL; 1665 1666 len = GetVar((UBYTE *)var, buf, (long)(IOSIZE - 1), (long)0); 1667 if (len >= 0) 1668 { 1669 retval = vim_strsave((char_u *)buf); 1670 alloced = retval; 1671 } 1672 1673 vim_free(buf); 1674 } 1675 1676 /* if $VIM is not defined, use "vim:" instead */ 1677 if (retval == NULL && STRCMP(var, "VIM") == 0) 1678 retval = (char_u *)"vim:"; 1679 1680 return retval; 1681 } 1682 1683 /* 1684 * Amiga version of setenv() with AmigaDOS 2.0 support. 1685 */ 1686 /* ARGSUSED */ 1687 int 1688 mch_setenv(var, value, x) 1689 char *var; 1690 char *value; 1691 int x; 1692 { 1693 #ifdef FEAT_ARP 1694 if (!dos2) 1695 return setenv(var, value); 1696 #endif 1697 1698 if (SetVar((UBYTE *)var, (UBYTE *)value, (LONG)-1, (ULONG)GVF_LOCAL_ONLY)) 1699 return 0; /* success */ 1700 return -1; /* failure */ 1701 } 1702