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