home *** CD-ROM | disk | FTP | other *** search
/ ftp.uv.es / 2014.11.ftp.uv.es.tar / ftp.uv.es / pub / unix / pine4.10.tar.gz / pine4.10.tar / pine4.10 / pico / osdep / dos next >
Text File  |  1998-08-13  |  14KB  |  620 lines

  1. #line 2 "osdep/dos"
  2. /*
  3.  * $Id: dos,v 1.7 1998/08/13 16:39:19 hubert Exp $
  4.  *
  5.  * Program:    Operating system dependent routines - MS DOS
  6.  *
  7.  *
  8.  * Michael Seibel
  9.  * Networks and Distributed Computing
  10.  * Computing and Communications
  11.  * University of Washington
  12.  * Administration Builiding, AG-44
  13.  * Seattle, Washington, 98195, USA
  14.  * Internet: mikes@cac.washington.edu
  15.  *
  16.  * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
  17.  *
  18.  *
  19.  * Pine and Pico are registered trademarks of the University of Washington.
  20.  * No commercial use of these trademarks may be made without prior written
  21.  * permission of the University of Washington.
  22.  * 
  23.  * Pine, Pico, and Pilot software and its included text are Copyright
  24.  * 1989-1998 by the University of Washington.
  25.  * 
  26.  * The full text of our legal notices is contained in the file called
  27.  * CPYRIGHT, included with this distribution.
  28.  *
  29.  *
  30.  * Notes:
  31.  *      - mouse support added (mss, 921215)
  32.  *
  33.  *  Portions of this code derived from MicroEMACS 3.10:
  34.  *
  35.  *    MSDOS.C:    Operating specific I/O and Spawning functions
  36.  *            under the MS/PCDOS operating system
  37.  *            for MicroEMACS 3.10
  38.  *            (C)opyright 1988 by Daniel M. Lawrence
  39.  *
  40.  */
  41.  
  42. #include    <fcntl.h>
  43. #include    <bios.h>
  44. #include        "dos_gen.h"
  45.  
  46.  
  47. /*
  48.  * Internal functions...
  49.  */
  50. int   enhanced_keybrd PROTO((void));
  51. int   dont_interrupt PROTO((void));
  52. int   interrupt_ok PROTO((void));
  53. int   specialkey PROTO((unsigned int));
  54. char *pfnexpand PROTO((char *, int));
  55. int   ssleep PROTO((long));
  56. int   sleep PROTO((int));
  57.  
  58.  
  59. /*
  60.  * Useful global def's
  61.  */
  62. int timeo = 0;
  63. int (*pcollator)();
  64. static int    enhncd = 0;        /* keyboard of enhanced variety? */
  65. union  REGS   rg;
  66. struct SREGS  segreg;
  67.  
  68. static    int oldbut;            /* Previous state of mouse buttons */
  69. static    unsigned short oldbreak;    /* Original state of break key */
  70. static    char ptmpfile[128];        /* popen temp file */
  71.  
  72.  
  73. /*
  74.  * Include generic DOS/Windows routines
  75.  */
  76. /* #include    "dos_gen.c" */
  77.  
  78.  
  79. /*
  80.  * DISable ctrl-break interruption
  81.  */
  82. dont_interrupt()
  83. {
  84.     /* get original value, to be restored later... */
  85.     rg.h.ah = 0x33;        /* control-break check dos call */
  86.     rg.h.al = 0;        /* get the current state */
  87.     rg.h.dl = 0;        /* pre-set it OFF */
  88.     intdos(&rg, &rg);        /* go for it! */
  89.     oldbreak = rg.h.dl;
  90.     /* kill the ctrl-break interupt */
  91.     rg.h.ah = 0x33;        /* control-break check dos call */
  92.     rg.h.al = 1;        /* set the current state */
  93.     rg.h.dl = 0;        /* set it OFF */
  94.     intdos(&rg, &rg);        /* go for it! */
  95. }
  96.  
  97.  
  98. /*
  99.  * re-enable ctrl-break interruption
  100.  */
  101. interrupt_ok()
  102. {
  103.     /* restore the ctrl-break interupt */
  104.     rg.h.ah = 0x33;        /* control-break check dos call */
  105.     rg.h.al = 1;        /* set to new state */
  106.     rg.h.dl = oldbreak;        /* set it to its original value */
  107.     intdos(&rg, &rg);    /* go for it! */
  108. }
  109.  
  110.  
  111. /*
  112.  * return true if an enhanced keyboard is present
  113.  */
  114. enhanced_keybrd()
  115. {
  116.     /* and check for extended keyboard */
  117.     rg.h.ah = 0x05;
  118.     rg.x.cx = 0xffff;
  119.     int86(BIOS_KEYBRD, &rg, &rg);
  120.     rg.h.ah = 0x10;
  121.     int86(BIOS_KEYBRD, &rg, &rg);
  122.     return(rg.x.ax == 0xffff);
  123. }
  124.  
  125.  
  126. /*
  127.  * This function is called once to set up the terminal device streams.
  128.  */
  129. ttopen()
  130. {
  131.     dont_interrupt();            /* don't allow interrupt */
  132.     enhncd = enhanced_keybrd();        /* check for extra keys */
  133. #if    MOUSE
  134.     init_mouse();
  135. #else    /* !MOUSE */
  136.     mexist = 0;
  137. #endif    /* MOUSE */
  138.     return(1);
  139. }
  140.  
  141.  
  142. /*
  143.  * ttresize - recompute the screen dimensions if necessary, and then
  144.  *          adjust pico's internal buffers accordingly
  145.  */
  146. void
  147. ttresize ()
  148. {
  149.     return;
  150. }
  151.  
  152.  
  153. #ifdef    MOUSE
  154. /* 
  155.  * init_mouse - check for and initialize mouse driver...
  156.  */
  157. init_mouse()
  158. {
  159.     long miaddr;        /* mouse interupt routine address */
  160.  
  161.     if(mexist)
  162.       return(TRUE);
  163.  
  164.     /* check if the mouse drive exists first */
  165.     rg.x.ax = 0x3533;        /* look at the interrupt 33 address */
  166.     intdosx(&rg, &rg, &segreg);
  167.     miaddr = (((long)segreg.es) << 16) + (long)rg.x.bx;
  168.     if (miaddr == 0 || *(char *)miaddr == 0xcf) {
  169.     mexist = FALSE;
  170.     return(TRUE);
  171.     }
  172.  
  173.     /* and then check for the mouse itself */
  174.     rg.x.ax = 0;            /* mouse status flag */
  175.     int86(BIOS_MOUSE, &rg, &rg);    /* check for the mouse interupt */
  176.     mexist = (rg.x.ax != 0);
  177.     nbuttons = rg.x.bx;
  178.  
  179.     if (mexist == FALSE)
  180.     return(TRUE);
  181.  
  182.     /* if the mouse exists.. get it in the upper right corner */
  183.     rg.x.ax = 4;            /* set mouse cursor position */
  184.     rg.x.cx = (term.t_ncol/2) << 3;    /* Center of display... */
  185.     rg.x.dx = 1 << 3;            /* Second line down */
  186.     int86(BIOS_MOUSE, &rg, &rg);
  187.  
  188.     /* and set its attributes */
  189.     rg.x.ax = 10;        /* set text cursor */
  190.     rg.x.bx = 0;        /* software text cursor please */
  191.     rg.x.cx = 0x77ff;    /* screen mask */
  192.     rg.x.dx = 0x7700;    /* cursor mask */
  193.     int86(BIOS_MOUSE, &rg, &rg);
  194.     return(TRUE);
  195. }
  196.  
  197.  
  198. /*
  199.  * mouseon - call made available for programs calling pico to turn ON the
  200.  *           mouse cursor.
  201.  */
  202. void
  203. mouseon()
  204. {
  205.     rg.x.ax = 1;            /* Show Cursor */
  206.     int86(BIOS_MOUSE, &rg, &rg); 
  207. }
  208.  
  209.  
  210. /*
  211.  * mouseon - call made available for programs calling pico to turn OFF the
  212.  *           mouse cursor.
  213.  */
  214. void
  215. mouseoff()
  216. {
  217.     rg.x.ax = 2;            /* Hide Cursor */
  218.     int86(BIOS_MOUSE, &rg, &rg);
  219. }
  220. #endif
  221.  
  222.  
  223. /*
  224.  * This function gets called just before we go back home to the command
  225.  * interpreter.
  226.  */
  227. ttclose()
  228. {
  229.     if(!Pmaster)
  230.       interrupt_ok();
  231.  
  232.     return(1);
  233. }
  234.  
  235.  
  236. /*
  237.  * Flush terminal buffer. Does real work where the terminal output is buffered
  238.  * up. A no-operation on systems where byte at a time terminal I/O is done.
  239.  */
  240. ttflush()
  241. {
  242.     return(1);
  243. }
  244.  
  245.  
  246. /*
  247.  * specialkey - return special key definition
  248.  */
  249. specialkey(kc)
  250. unsigned  kc;
  251. {
  252.     switch(kc){
  253.     case 0x3b00 : return(F1);
  254.     case 0x3c00 : return(F2);
  255.     case 0x3d00 : return(F3);
  256.     case 0x3e00 : return(F4);
  257.     case 0x3f00 : return(F5);
  258.     case 0x4000 : return(F6);
  259.     case 0x4100 : return(F7);
  260.     case 0x4200 : return(F8);
  261.     case 0x4300 : return(F9);
  262.     case 0x4400 : return(F10);
  263.     case 0x8500 : return(F11);
  264.     case 0x8600 : return(F12);
  265.     case 0x4800 : return(KEY_UP);
  266.     case 0x5000 : return(KEY_DOWN);
  267.     case 0x4b00 : return(KEY_LEFT);
  268.     case 0x4d00 : return(KEY_RIGHT);
  269.     case 0x4700 : return(KEY_HOME);
  270.     case 0x4f00 : return(KEY_END);
  271.     case 0x4900 : return(KEY_PGUP);
  272.     case 0x5100 : return(KEY_PGDN);
  273.     case 0x5300 : return(KEY_DEL);
  274.     case 0x48e0 : return(KEY_UP);            /* grey key version */
  275.     case 0x50e0 : return(KEY_DOWN);            /* grey key version */
  276.     case 0x4be0 : return(KEY_LEFT);            /* grey key version */
  277.     case 0x4de0 : return(KEY_RIGHT);        /* grey key version */
  278.     case 0x47e0 : return(KEY_HOME);            /* grey key version */
  279.     case 0x4fe0 : return(KEY_END);            /* grey key version */
  280.     case 0x49e0 : return(KEY_PGUP);            /* grey key version */
  281.     case 0x51e0 : return(KEY_PGDN);            /* grey key version */
  282.     case 0x53e0 : return(KEY_DEL);            /* grey key version */
  283.     default     : return(NODATA);
  284.     }
  285. }
  286.  
  287.  
  288. /*
  289.  * Read a character from the terminal, performing no editing and doing no echo
  290.  * at all. Also mouse events are forced into the input stream here.
  291.  */
  292. int
  293. ttgetc(return_on_intr, recorder, bail_handler)
  294.     int return_on_intr;
  295.     int (*recorder)();
  296.     int (*bail_handler)();
  297. {
  298.     return(_bios_keybrd(enhncd ? _NKEYBRD_READ : _KEYBRD_READ));
  299. }
  300.  
  301.  
  302. /*
  303.  * ctrlkey - used to check if the key hit was a control key.
  304.  */
  305. ctrlkey()
  306. {
  307.     return(_bios_keybrd(enhncd ? _NKEYBRD_SHIFTSTATUS : _KEYBRD_SHIFTSTATUS)
  308.             & 0x04);
  309. }
  310.  
  311.  
  312. /*
  313.  * win_multiplex - give DOS in a window a shot at the CPU
  314.  */
  315. win_multiplex()
  316. {
  317.     rg.x.ax = 0x1680;
  318.     int86(DOS_MULTIPLEX, &rg, &rg);
  319. }
  320.  
  321.  
  322. /*
  323.  * Read in a key.
  324.  * Do the standard keyboard preprocessing. Convert the keys to the internal
  325.  * character set.  Resolves escape sequences and returns no-op if global
  326.  * timeout value exceeded.
  327.  */
  328. GetKey()
  329. {
  330.     unsigned ch = 0, lch, intrupt = 0;
  331.     long timein;
  332.  
  333.     if(mexist || timeo){
  334.     timein = time(0L);
  335. #ifdef    MOUSE
  336.     if(mexist){
  337.         rg.x.ax = 1;            /* Show Cursor */
  338.         int86(BIOS_MOUSE, &rg, &rg); 
  339.     }
  340. #endif
  341.     while(!_bios_keybrd(enhncd ? _NKEYBRD_READY : _KEYBRD_READY)){
  342. #if    MOUSE
  343.         if(timeo && time(0L) >= timein+timeo){
  344.         if(mexist){
  345.             rg.x.ax = 2;        /* Hide Cursor */
  346.             int86(BIOS_MOUSE, &rg, &rg);
  347.         }
  348.         return(NODATA);
  349.         }
  350.  
  351.         if(checkmouse(&ch,0,0,0)){        /* something happen ?? */
  352.         if(mexist){
  353.             rg.x.ax = 2;        /* Hide Cursor */
  354.             int86(BIOS_MOUSE, &rg, &rg);
  355.         }
  356.         curwp->w_flag |= WFHARD;
  357.         return(ch);
  358.         }
  359. #else
  360.         if(time(0L) >= timein+timeo)
  361.           return(NODATA);
  362. #endif    /* MOUSE */
  363.  
  364.         /*
  365.          * Surrender the CPU...
  366.          */
  367.         if(!intrupt++)
  368.           win_multiplex();
  369.         }
  370. #ifdef    MOUSE
  371.     if(mexist){
  372.         rg.x.ax = 2;            /* Hide Cursor */
  373.         int86(BIOS_MOUSE, &rg, &rg);
  374.     }
  375. #endif    /* MOUSE */
  376.     }
  377.  
  378.     ch  = (*term.t_getchar)(0, NULL, NULL);
  379.     lch = (ch&0xff);
  380.     return((lch && (lch != 0xe0 || !(ch & 0xff00))) 
  381.             ? (lch < ' ') ? (CTRL|(lch + '@')) 
  382.                           : (lch == ' ' && ctrlkey()) ? (CTRL|'@') : lch
  383.             : specialkey(ch));
  384. }
  385.  
  386.  
  387. #if    MOUSE
  388. /* 
  389.  * checkmouse - look for mouse events in key menu and return 
  390.  *              appropriate value.
  391.  *   NOTE: "down", "xxx", and "yyy" aren't used under DOS.
  392.  */
  393. int
  394. checkmouse(ch, down, xxx, yyy)
  395. unsigned *ch;
  396. int      down, xxx, yyy;
  397. {
  398.     register int k;        /* current bit/button of mouse */
  399.     int mcol;            /* current mouse column */
  400.     int mrow;            /* current mouse row */
  401.     int sstate;            /* current shift key status */
  402.     int newbut;            /* new state of the mouse buttons */
  403.     int button;
  404.     int rv = 0;
  405.  
  406.     if(!mexist)
  407.     return(FALSE);
  408.  
  409.     /* check to see if any mouse buttons are different */
  410.     rg.x.ax = 3;        /* Get button status and mouse position */
  411.     int86(BIOS_MOUSE, &rg, &rg);
  412.     newbut = rg.x.bx;
  413.     mcol = rg.x.cx >> 3;
  414.     mrow = (rg.x.dx >> 3);
  415.  
  416.     /* only notice changes */
  417.     if (oldbut == newbut)
  418.     return(FALSE);
  419.  
  420.     if (mcol < 0)        /* only on screen presses are legit! */
  421.     mcol = 0;
  422.     if (mrow < 0)
  423.     mrow = 0;
  424.  
  425.     sstate = 0;            /* get the shift key status as well */
  426.     rg.h.ah = 2;
  427.     int86(BIOS_KEYBRD, &rg, &rg);
  428.     sstate = rg.h.al;
  429.  
  430.     button = M_BUTTON_LEFT;
  431.     for (k=1; k != (1 << nbuttons); k = k<<1) {
  432.     /* For each button on the mouse */
  433.     if ((oldbut&k) != (newbut&k)) {
  434.         if(k == 1){
  435.         static int oindex;
  436.         int i = 0;
  437.         MENUITEM *mp;
  438.  
  439.         if(newbut&k)            /* button down */
  440.           oindex = -1;
  441.  
  442.         for(mp = mfunc; mp; mp = mp->next)
  443.           if(mp->action && M_ACTIVE(mrow, mcol, mp))
  444.             break;
  445.  
  446.         if(mp){
  447.             unsigned long r;
  448.  
  449.             r = (*mp->action)((newbut&k) ? M_EVENT_DOWN : M_EVENT_UP,
  450.                       mrow, mcol, button, 0);
  451.             if(r & 0xffff){
  452.             *ch = (unsigned)((r>>16)&0xffff);
  453.             rv  = TRUE;
  454.             }
  455.         }
  456.         else{
  457.             while(1){    /* see if we understand event */
  458.             if(i >= 12){
  459.                 i = -1;
  460.                 break;
  461.             }
  462.  
  463.             if(M_ACTIVE(mrow, mcol, &menuitems[i]))
  464.               break;
  465.  
  466.             i++;
  467.             }
  468.  
  469.             if(newbut&k){            /* button down */
  470.             oindex = i;            /* remember where */
  471.             if(i != -1)            /* invert label */
  472.               invert_label(1, &menuitems[i]);
  473.             }
  474.             else{                /* button up */
  475.             if(oindex != -1){
  476.                 if(i == oindex){
  477.                 *ch = menuitems[i].val;
  478.                 rv = 1;
  479.                 }
  480.             }
  481.             }
  482.         }
  483.  
  484.         if(!(newbut&k) && oindex != -1)
  485.           invert_label(0, &menuitems[oindex]);    /* restore label */
  486.         }
  487.  
  488.         oldbut = newbut;
  489.         return(rv);
  490.     }
  491.  
  492.     ++button;
  493.     }
  494.  
  495.     return(FALSE);
  496. }
  497.  
  498.  
  499. /*
  500.  * invert_label - highlight the label of the given menu item.
  501.  */
  502. void
  503. invert_label(state, m)
  504. int state;
  505. MENUITEM *m;
  506. {
  507.     int i, j, r, c, p, col_offset;
  508.     char *lp;
  509.     int old_state = getrevstate();
  510.  
  511.     if(m->val == mnoop)
  512.       return;
  513.  
  514.     rg.h.ah = 3;                /* get cursor position */
  515.     int86(BIOS_VIDEO, &rg, &rg);
  516.     p = rg.h.bh;
  517.     c = rg.h.dl;
  518.     r = rg.h.dh;
  519.     rg.x.ax = 2;                /* Hide Cursor */
  520.     int86(BIOS_MOUSE, &rg, &rg);
  521.     /*
  522.      * Leave the command name bold
  523.      */
  524.     col_offset = (state || !(lp=strchr(m->label, ' '))) ? 0 : (lp - m->label);
  525.     (*term.t_move)(m->tl.r, m->tl.c + col_offset);
  526.     (*term.t_rev)(state);
  527.     for(i = m->tl.r; i <= m->br.r; i++)
  528.       for(j = m->tl.c + col_offset; j <= m->br.c; j++)
  529.     if(i == m->lbl.r && j == m->lbl.c + col_offset){ /* show label?? */
  530.         lp = m->label + col_offset;
  531.         while(*lp && j++ < m->br.c)
  532.           (*term.t_putchar)(*lp++);
  533.  
  534.         continue;
  535.     }
  536.     else
  537.       (*term.t_putchar)(' ');
  538.  
  539.     (*term.t_rev)(old_state);
  540.     rg.h.ah = 2;
  541.     rg.h.bh = p;
  542.     rg.h.dh = r;
  543.     rg.h.dl = c;
  544.     int86(BIOS_VIDEO, &rg, &rg);        /* restore old position */
  545.     rg.x.ax = 1;                /* Show Cursor */
  546.     int86(BIOS_MOUSE, &rg, &rg);
  547. }
  548. #endif    /* MOUSE */
  549.  
  550.  
  551. /*
  552.  * alt_editor - fork off an alternate editor for mail message composition
  553.  *
  554.  *  NOTE: Not yet used under DOS
  555.  */
  556. alt_editor(f, n)
  557.     int f, n;
  558. {
  559.     return(-1);
  560. }
  561.  
  562.  
  563. /*
  564.  *  bktoshell - suspend and wait to be woken up
  565.  */
  566. int
  567. bktoshell()        /* suspend MicroEMACS and wait to wake up */
  568. {
  569.     int i;
  570.     char *shell;
  571.  
  572.     (*term.t_move)(term.t_nrow, 0);
  573.     if(system((shell = getenv("COMSPEC")) ? shell : "command") == -1)
  574.       emlwrite("Error loading %s", shell ? shell : "COMMAND.COM");
  575.     else
  576.       refresh(0, 1);            /* redraw */
  577.     
  578.     return(1);
  579. }
  580.  
  581.  
  582. /*
  583.  * P_open - run the given command in a sub-shell returning a file pointer
  584.  *        from which to read the output
  585.  *
  586.  * note:
  587.  *    For OS's other than unix, you will have to rewrite this function.
  588.  *    Hopefully it'll be easy to exec the command into a temporary file, 
  589.  *    and return a file pointer to that opened file or something.
  590.  */
  591. FILE *P_open(c)
  592. char *c;
  593. {
  594.     char cmdbuf[NLINE];
  595.     sprintf(ptmpfile, tmpnam(NULL));
  596.     sprintf(cmdbuf, "%s > %s", c, ptmpfile);
  597.     if(system(cmdbuf) == -1){
  598.     unlink(ptmpfile);
  599.     return(NULL);
  600.     }
  601.  
  602.     return(fopen(ptmpfile, "r"));
  603. }
  604.  
  605.  
  606.  
  607. /*
  608.  * P_close - close the given descriptor
  609.  *
  610.  */
  611. P_close(fp)
  612. FILE *fp;
  613. {
  614.     fclose(fp);            /* doesn't handle return codes */
  615.     unlink(ptmpfile);
  616.     return(0);;
  617. }
  618.  
  619.  
  620.