home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 8 / FreshFishVol8-CD2.bin / bbs / util / vim-3.0.lha / Vim / src / msdos.c < prev    next >
C/C++ Source or Header  |  1994-08-12  |  19KB  |  1,008 lines

  1. /* vi:ts=4:sw=4
  2.  *
  3.  * VIM - Vi IMproved        by Bram Moolenaar
  4.  *
  5.  * Read the file "credits.txt" for a list of people who contributed.
  6.  * Read the file "uganda.txt" for copying and usage conditions.
  7.  */
  8.  
  9. /*
  10.  * msdos.c
  11.  *
  12.  * MSDOS system-dependent routines.
  13.  * A cheap plastic imitation of the amiga dependent code.
  14.  * A lot in this file was made by Juergen Weigert (jw).
  15.  */
  16.  
  17. #include <io.h>
  18. #include "vim.h"
  19. #include "globals.h"
  20. #include "param.h"
  21. #include "proto.h"
  22. #include <conio.h>
  23. #include <fcntl.h>
  24. #include <bios.h>
  25. #include <alloc.h>
  26.  
  27. static int WaitForChar __ARGS((int));
  28. static int change_drive __ARGS((int));
  29. static int cbrk_handler __ARGS(());
  30.  
  31. typedef struct filelist
  32. {
  33.     char_u    **file;
  34.     int        nfiles;
  35.     int        maxfiles;
  36. } FileList;
  37.  
  38. static void        addfile __ARGS((FileList *, char_u *, int));
  39. static int        pstrcmp();    /* __ARGS((char **, char **)); BCC does not like this */
  40. static void        strlowcpy __ARGS((char_u *, char_u *));
  41. static int        expandpath __ARGS((FileList *, char_u *, int, int, int));
  42.  
  43. static int cbrk_pressed = FALSE;    /* set by ctrl-break interrupt */
  44. static int ctrlc_pressed = FALSE;    /* set when ctrl-C or ctrl-break detected */
  45. static int delayed_redraw = FALSE;    /* set when ctrl-C detected */
  46.  
  47.     long
  48. mch_avail_mem(special)
  49.     int special;
  50. {
  51.     return coreleft();
  52. }
  53.  
  54.     void
  55. vim_delay()
  56. {
  57.     delay(500);
  58. }
  59.  
  60. /*
  61.  * this version of remove is not scared by a readonly (backup) file
  62.  *
  63.  * returns -1 on error, 0 otherwise (just like remove())
  64.  */
  65.     int
  66. vim_remove(name)
  67.     char_u *name;
  68. {
  69.     (void)setperm(name, 0);    /* default permissions */
  70.     return unlink(name);
  71. }
  72.  
  73. /*
  74.  * mch_write(): write the output buffer to the screen
  75.  */
  76.     void
  77. mch_write(s, len)
  78.     char_u    *s;
  79.     int        len;
  80. {
  81.     char_u    *p;
  82.     int        row, col;
  83.  
  84.     if (term_console)        /* translate ESC | sequences into bios calls */
  85.         while (len--)
  86.         {
  87.             if (s[0] == '\n')
  88.                 putch('\r');
  89.             else if (s[0] == ESC && len > 1 && s[1] == '|')
  90.             {
  91.                 switch (s[2])
  92.                 {
  93.                 case 'J':    clrscr();
  94.                             goto got3;
  95.  
  96.                 case 'K':    clreol();
  97.                             goto got3;
  98.  
  99.                 case 'L':    insline();
  100.                             goto got3;
  101.  
  102.                 case 'M':    delline();
  103. got3:                        s += 3;
  104.                             len -= 2;
  105.                             continue;
  106.  
  107.                 case '0':
  108.                 case '1':
  109.                 case '2':
  110.                 case '3':
  111.                 case '4':
  112.                 case '5':
  113.                 case '6':
  114.                 case '7':
  115.                 case '8':
  116.                 case '9':    p = s + 2;
  117.                             row = getdigits(&p);        /* no check for length! */
  118.                             if (p > s + len)
  119.                                 break;
  120.                             if (*p == ';')
  121.                             {
  122.                                 ++p;
  123.                                 col = getdigits(&p);    /* no check for length! */
  124.                                 if (p > s + len)
  125.                                     break;
  126.                                 if (*p == 'H' || *p == 'r')
  127.                                 {
  128.                                     if (*p == 'H')        /* set cursor position */
  129.                                         gotoxy(col, row);
  130.                                     else                /* set scroll region  */
  131.                                         window(1, row, Columns, col);
  132.                                     len -= p - s;
  133.                                     s = p + 1;
  134.                                     continue;
  135.                                 }
  136.                             }
  137.                             else if (*p == 'm')
  138.                             {
  139.                                 if (row == 0)
  140.                                     normvideo();
  141.                                 else
  142.                                     textattr(row);
  143.                                 len -= p - s;
  144.                                 s = p + 1;
  145.                                 continue;
  146.                             }
  147.                 }
  148.             }
  149.             putch(*s++);
  150.         }
  151.     else
  152.         write(1, s, (unsigned)len);
  153. }
  154.  
  155. #define POLL_SPEED 10    /* milliseconds between polls */
  156.  
  157. /*
  158.  * Simulate WaitForChar() by slowly polling with bioskey(1) or kbhit().
  159.  *
  160.  * If Vim should work over the serial line after a 'ctty com1' we must use
  161.  * kbhit() and getch(). (jw)
  162.  * Usually kbhit() is not used, because then CTRL-C and CTRL-P
  163.  * will be catched by DOS (mool).
  164.  *
  165.  * return TRUE if a character is available, FALSE otherwise
  166.  */
  167.  
  168.     static int
  169. WaitForChar(msec)
  170.     int msec;
  171. {
  172.     for (;;)
  173.     {
  174.         if ((p_biosk ? bioskey(1) : kbhit()) || cbrk_pressed)
  175.             return TRUE;
  176.         if (msec <= 0)
  177.             break;
  178.         delay(POLL_SPEED);
  179.         msec -= POLL_SPEED;
  180.     }
  181.     return FALSE;
  182. }
  183.  
  184. /*
  185.  * GetChars(): low level input funcion.
  186.  * Get a characters from the keyboard.
  187.  * If time == 0 do not wait for characters.
  188.  * If time == n wait a short time for characters.
  189.  * If time == -1 wait forever for characters.
  190.  *
  191.  * return the number of characters obtained
  192.  */
  193.     int
  194. GetChars(buf, maxlen, time)
  195.     char_u        *buf;
  196.     int         maxlen;
  197.     int         time;
  198. {
  199.     int         len = 0;
  200.     int            c;
  201.  
  202. /*
  203.  * if we got a ctrl-C when we were busy, there will be a "^C" somewhere
  204.  * on the sceen, so we need to redisplay it.
  205.  */
  206.     if (delayed_redraw)
  207.     {
  208.         delayed_redraw = FALSE;
  209.         updateScreen(CLEAR);
  210.         setcursor();
  211.         flushbuf();
  212.     }
  213.  
  214.     if (time >= 0)
  215.     {
  216.         if (WaitForChar(time) == 0)     /* no character available */
  217.             return 0;
  218.     }
  219.     else    /* time == -1 */
  220.     {
  221.     /*
  222.      * If there is no character available within 2 seconds (default)
  223.      * write the autoscript file to disk
  224.      */
  225.         if (WaitForChar((int)p_ut) == 0)
  226.             updatescript(0);
  227.     }
  228.  
  229. /*
  230.  * Try to read as many characters as there are.
  231.  * Works for the controlling tty only.
  232.  */
  233.     --maxlen;        /* may get two chars at once */
  234.     /*
  235.      * we will get at least one key. Get more if they are available
  236.      * After a ctrl-break we have to read a 0 (!) from the buffer.
  237.      * bioskey(1) will return 0 if no key is available and when a
  238.      * ctrl-break was typed. When ctrl-break is hit, this does not always
  239.      * implies a key hit.
  240.      */
  241.     cbrk_pressed = FALSE;
  242.     if (p_biosk)
  243.         while ((len == 0 || bioskey(1)) && len < maxlen)
  244.         {
  245.             c = bioskey(0);            /* get the key */
  246.             if (c == 0)                /* ctrl-break */
  247.                 c = 3;                /* return a CTRL-C */
  248.             if ((c & 0xff) == 0)
  249.             {
  250.                 if (c == 0x0300)        /* CTRL-@ is 0x0300, translated into K_ZERO */
  251.                     c = K_ZERO;
  252.                 else        /* extended key code 0xnn00 translated into K_NUL, nn */
  253.                 {
  254.                     c >>= 8;
  255.                     *buf++ = K_NUL;
  256.                     ++len;
  257.                 }
  258.             }
  259.  
  260.             *buf++ = c;
  261.             len++;
  262.         }
  263.     else
  264.         while ((len == 0 || kbhit()) && len < maxlen)
  265.         {
  266.             switch (c = getch())
  267.             {
  268.             case 0:
  269.                     *buf++ = K_NUL;
  270.                     break;
  271.             case 3:
  272.                     cbrk_pressed = TRUE;
  273.                     /*FALLTHROUGH*/
  274.             default:
  275.                     *buf++ = c;
  276.             }
  277.             len++;
  278.         }
  279.     return len;
  280. }
  281.  
  282. /*
  283.  * return non-zero if a character is available
  284.  */
  285.     int
  286. mch_char_avail()
  287. {
  288.     return WaitForChar(0);
  289. }
  290.  
  291. /*
  292.  * We have no job control, fake it by starting a new shell.
  293.  */
  294.     void
  295. mch_suspend()
  296. {
  297.     OUTSTR("new shell started\n");
  298.     (void)call_shell(NULL, 0, TRUE);
  299. }
  300.  
  301. extern int _fmode;
  302. /*
  303.  * we do not use windows, there is not much to do here
  304.  */
  305.     void
  306. mch_windinit()
  307. {
  308.     _fmode = O_BINARY;        /* we do our own CR-LF translation */
  309.     flushbuf();
  310.     (void)mch_get_winsize();
  311. }
  312.  
  313.     void
  314. check_win(argc, argv)
  315.     int        argc;
  316.     char    **argv;
  317. {
  318.     if (!isatty(0) || !isatty(1))
  319.     {
  320.         fprintf(stderr, "VIM: no controlling terminal\n");
  321.         exit(2);
  322.     }
  323.     /*
  324.      * In some cases with DOS 6.0 on a NEC notebook there is a 12 seconds
  325.      * delay when starting up that can be avoided by the next two lines.
  326.      * Don't ask me why!
  327.      * This could be fixed by removing setver.sys from config.sys. Forget it.
  328.     gotoxy(1,1);
  329.     cputs(" ");
  330.      */
  331. }
  332.  
  333. /*
  334.  * fname_case(): Set the case of the filename, if it already exists.
  335.  *                 msdos filesystem is far to primitive for that. do nothing.
  336.  */
  337.     void
  338. fname_case(name)
  339.     char_u *name;
  340. {
  341. }
  342.  
  343. /*
  344.  * mch_settitle(): set titlebar of our window.
  345.  * Dos console has no title.
  346.  */
  347.     void
  348. mch_settitle(title, icon)
  349.     char_u *title;
  350.     char_u *icon;
  351. {
  352. }
  353.  
  354. /*
  355.  * Restore the window/icon title. (which we don't have)
  356.  */
  357.     void
  358. mch_restore_title(which)
  359.     int which;
  360. {
  361. }
  362.  
  363. /*
  364.  * Get name of current directory into buffer 'buf' of length 'len' bytes.
  365.  * Return OK for success, FAIL for failure.
  366.  */
  367.     int
  368. vim_dirname(buf, len)
  369.     char_u    *buf;
  370.     int        len;
  371. {
  372.     return (getcwd(buf, len) != NULL ? OK : FAIL);
  373. }
  374.  
  375. /*
  376.  * Change default drive (just like _chdrive of Borland C 3.1)
  377.  */
  378.     static int
  379. change_drive(drive)
  380.     int drive;
  381. {
  382.     unsigned dummy;
  383.     union REGS regs;
  384.  
  385.     regs.h.ah = 0x0e;
  386.     regs.h.dl = drive - 1;
  387.     intdos(®s, ®s);    /* set default drive */
  388.     regs.h.ah = 0x19;
  389.     intdos(®s, ®s);    /* get default drive */
  390.     if (regs.h.al == drive - 1)
  391.         return 0;
  392.     else
  393.         return -1;
  394. }
  395.  
  396. /*
  397.  * get absolute filename into buffer 'buf' of length 'len' bytes
  398.  *
  399.  * return FAIL for failure, OK otherwise
  400.  */
  401.     int
  402. FullName(fname, buf, len)
  403.     char_u    *fname, *buf;
  404.     int        len;
  405. {
  406.     if (fname == NULL)    /* always fail */
  407.     {
  408.         *buf = NUL;
  409.         return FAIL;
  410.     }
  411.  
  412.     if (isFullName(fname))        /* allready expanded */
  413.     {
  414.         STRNCPY(buf, fname, len);
  415.         return OK;
  416.     }
  417.  
  418. #ifdef __BORLANDC__        /* the old Turbo C does not have this */
  419.     if (_fullpath(buf, fname, len) == NULL)
  420.     {
  421.         STRNCPY(buf, fname, len);    /* failed, use