home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / AP / JED / JED097-1.TAR / jed / src / ibmpc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-12  |  11.0 KB  |  556 lines

  1. /*
  2.  *  Copyright (c) 1992, 1994 John E. Davis  (davis@amy.tch.harvard.edu)
  3.  *  All Rights Reserved.
  4.  */
  5. #include <stdio.h>
  6. #include <conio.h>
  7. #include <string.h>
  8. #include <process.h>
  9. #include "config.h"
  10. #include "sysdep.h"
  11.  
  12. #ifdef HAS_MOUSE
  13. #include "pcmouse.h"
  14. #endif
  15.  
  16. #include <dir.h>
  17. #include <dos.h>
  18. #include <bios.h>
  19. #include <io.h>
  20. #include <conio.h>
  21. #include <time.h>
  22. #include <stddef.h>
  23.  
  24. /* for stat */
  25. #include <sys/stat.h>
  26. #include <errno.h>
  27.  
  28.  
  29. #ifdef __cplusplus
  30. #define _DOTS_ ...
  31. #else
  32. #define _DOTS_ 
  33. #endif
  34.  
  35. void interrupt (*oldint9)(_DOTS_);
  36.  
  37. static unsigned char far *shift = (unsigned char far *) 0x417;
  38. static unsigned int far *kbptr = (unsigned int far *) 0x41a;
  39. static unsigned int far *kbnext = (unsigned int far *) 0x41c;
  40. static unsigned int far *kbbeg = (unsigned int far *) 0x480;
  41. static unsigned int far *kbend = (unsigned int far *) 0x482;
  42.  
  43. int Abort_Char = 34;
  44.  
  45. #include "dos_os2.c"
  46.  
  47. /* Macro to get char from BIOS not dos */
  48. void interrupt int9_handler(_DOTS_)
  49. {
  50.    unsigned int scan = (unsigned int) Abort_Char; /* 34 = scan code for ^G */
  51.    unsigned char s, s1;
  52.    unsigned int offset, f1_scan = 0x3B00;  /* f1 key */
  53.    unsigned int *p;
  54.    unsigned int numlock = 0x45;
  55.    
  56.  
  57.    s1 = *shift & 0xF;  /* ignoring caps, ins, num lock, scroll lock */
  58.    s = inp(0x60);
  59.    if (s1 & 0x04)      /* control key */
  60.      {
  61.     if (s == scan)
  62.       {
  63.          if (Ignore_User_Abort == 0) SLang_Error = 2;
  64.          SLKeyBoard_Quit = 1;
  65.       }
  66.     else if (s == 28)   /* Control - enter, ignore it!! */
  67.       {
  68.          s = inp(0x61);
  69.          outportb(0x61, s | 0x80);
  70.          outportb(0x61, s);
  71.          outportb(0x20, 0x20);
  72.          return;
  73.       }
  74.      }
  75.    else if (NumLock_Is_Gold && ((s & 0x7F) == numlock))
  76.      {
  77.     if (s == numlock)
  78.       {
  79.          offset = *kbnext;
  80.          offset += 2;
  81.          if (offset == *kbend) offset = *kbbeg;
  82.          if (offset != *kbptr)  /* buffer not full */
  83.            {
  84.           p = (unsigned int *) (0x400L + (*kbnext));
  85.           *p = f1_scan;
  86.           *kbnext = offset;
  87.            }
  88.       }
  89.     s = inp(0x61);
  90.     outportb(0x61, s | 0x80);
  91.     outportb(0x61, s);
  92.     outportb(0x20, 0x20);
  93.     return;
  94.      }
  95.    (*oldint9)();
  96. }
  97.  
  98. void init_int9_handler(void)
  99. {
  100.    oldint9 = getvect(9);
  101.    setvect(9, int9_handler);
  102. }
  103.  
  104. void restore_int9_handler(void)
  105. {
  106.    setvect(9, oldint9);
  107. }
  108.  
  109. static void set_ctrl_break(int state)
  110. {
  111.    static int prev = 0;
  112.  
  113.    asm {
  114.       mov dl, byte ptr prev
  115.       mov ax, state
  116.       cmp ax, 0
  117.       jne L1
  118.       mov ah, 33h
  119.       mov al, 0
  120.       mov dl, byte ptr prev
  121.       int 21h
  122.       xor ax, ax
  123.       mov al, dl
  124.       mov prev, ax
  125.       mov dl, 0
  126.    }
  127.    L1:
  128.    asm {
  129.       mov al, 1
  130.       mov ah, 33h
  131.       int 21h
  132.    }   
  133. }
  134.  
  135. #if 0
  136. /* Here I just flag the error and return to the user-- hopefully jed will
  137.    catch it and user will know what to do. */
  138. static char *int24_errs[] = 
  139. {
  140.    "write protect",
  141.    "bad unit",
  142.    "drive not ready",
  143.    "unknown",
  144.    "CRC error",
  145.    "request error",
  146.    "seek error",
  147.    "unknown media",
  148.    "sector not found",
  149.    "printer out of paper",
  150.    "general write failure",
  151.    "general read failure",
  152.    "general failure", "reserved", "reserved", "invalid disk change"
  153. };
  154.  
  155. int int24_handler(int err, int ax, int bp, int si)
  156. {
  157.    unsigned int di;
  158.    
  159.    di = _DI;
  160.    (void) ax;
  161.    (void) bp;
  162.    msg_error(int24_errors[di & 0x000F]);
  163. }
  164. #endif
  165.  
  166. static int ctrl_break(void)
  167. {
  168.    msg_error("Control Break ignored!");
  169.    return(1);
  170. }
  171.  
  172.  
  173. #define BIOSKEY(x) bioskey((x) | bios_key_f)
  174. static int bios_key_f;
  175. void init_tty()
  176. {
  177.    bios_key_f = peekb(0x40,0x96) & 0x10; /* enhanced keyboard flag */
  178.    set_ctrl_break(0); 
  179.    ctrlbrk(ctrl_break);
  180.    init_int9_handler();
  181. }
  182.  
  183. void reset_tty()
  184. {
  185.    restore_int9_handler();
  186.    set_ctrl_break(1);
  187.    if (Batch) return;
  188.    SLtt_reset_video();
  189. }
  190.  
  191.  
  192. /* Here I also map keys to edt keys */
  193. unsigned char sys_getkey()
  194. {
  195.    char *keypad_scan = 
  196.       "\x4e\x53\x52\x4f\x50\x51\x4b\x4c\x4d\x47\x48\x49\x37\x4a";
  197.    char *normal = "!@#$%^&*()-=\t*\0177QWERTYUIOP[]\r*ASDFGHJKL;'`*\\ZXCVBNM<>/";
  198.    char *edt_chars = "lnpqrstuvwxyRS";
  199.    int bra = 'O', P = 'P', keypad, weird;
  200.    char *p;
  201.    unsigned int c, c1, shft;
  202.    unsigned int i;
  203.    
  204.    weird = 300;
  205.    if (BIOSKEY(1) == 0) while (!sys_input_pending(&weird))
  206.      {
  207.     if (Display_Time)
  208.       {
  209.          JWindow->trashed = 1;
  210.          update((Line *) NULL, 0, 1);
  211.       }
  212.      }
  213. #ifdef HAS_MOUSE
  214.    /* This can only be set by the mouse */
  215.    if (Input_Buffer_Len) return my_getkey ();
  216. #endif
  217.    
  218.    i = BIOSKEY(0);
  219.    c = i & 0xFF;
  220.    c1 = i >> 8;
  221.    
  222.    keypad = (c1 > 0x36) && NumLock_Is_Gold && (bios_key_f == 0x10);
  223.    /* allow Shift-keypad to give non edt keypad chars */
  224.    shft = *shift & 0xF;
  225.    keypad = keypad && !(shft & 0x3);
  226.    
  227.    
  228.    /* This is for the damned enter and slash keys */
  229.    weird = keypad && ((c1 == 0xE0) && ((c == 0xD) || (c == 0x2F)));
  230.    
  231.    keypad = keypad && (c != 0xE0);  /* excludes small keypad */
  232.    
  233.    if ((c == 8) && ((i >> 8) == 0x0e)) c =127;
  234.    else if ((c == 32) && (shft & 0x04))    /* ^ space = ^@ */
  235.      {
  236.     c = 3;
  237.     ungetkey((int *) &c);
  238.     c = 0;
  239.      }
  240.    else if (weird || (keypad && (NULL != (p = strchr(keypad_scan, c1)))))
  241.      {
  242.     if (c1 == 0xE0) if (c == 0x2f) c = 'Q'; else c = 'M';
  243.     else c = (unsigned int) edt_chars[(int) (p - keypad_scan)];
  244.     ungetkey((int *) &c);
  245.     ungetkey((int *) &bra);
  246.     c = 27;
  247.      }
  248.    else if ((!c) || ((c == 0xe0) && (bios_key_f) && (c1 > 0x43)))
  249.      {
  250.     if (NumLock_Is_Gold && (c1 == 0x3B))
  251.       {
  252.          ungetkey(&P); ungetkey(&bra); c = 27;
  253.       }
  254.     /* if key is 5 of keypad, get another char */
  255.     else if ((c1 == 'L') && bios_key_f && (c == 0)) return(sys_getkey());
  256.     else 
  257.       {
  258.          if ((shft == 0x8) && (c == 0) && PC_Alt_Char)
  259.            {
  260.           if ((c1 >= 14) && (c1 <= 53))
  261.             {
  262.                c1 = (unsigned int) normal[c1];
  263.                c = PC_Alt_Char;
  264.             }
  265.           else if ((c1 >= 120) && (c1 <= 131))
  266.             {
  267.                c1 = (unsigned int) normal[c1 - 120];
  268.                c = PC_Alt_Char;
  269.             }
  270.           else if (c1 == 165) /* tab */
  271.             {
  272.                c1 = (unsigned int) normal[c1 - 165 + 12];
  273.                c = PC_Alt_Char;
  274.             }
  275.            }
  276.          else c = 0;
  277.          ungetkey((int *) &c1);
  278.       }
  279.      }
  280.    return(c);
  281. }
  282.  
  283. /* sleep for *tsecs tenths of a sec waiting for input */
  284. static int sys_input_pending(int *tsecs)
  285. {
  286.    int count = *tsecs * 5;
  287.    
  288.    if (Batch || Input_Buffer_Len) return(Input_Buffer_Len);
  289.    
  290.    if (count)
  291.      {
  292.     while(count > 0)
  293.       {
  294.          delay(20);               /* 20 ms or 1/50 sec */
  295.          if (BIOSKEY(1)
  296. #ifdef HAS_MOUSE
  297.          || mouse_input()
  298. #endif
  299.          ) break;
  300.          count--;
  301.       }
  302.     return(count);
  303.      }
  304.    else return(
  305.            BIOSKEY(1)
  306. #ifdef HAS_MOUSE
  307.            || mouse_input()
  308. #endif
  309.            );
  310.            
  311. }
  312.  
  313. /* Thanks to Robert Schmidt - robert@alkymi.unit.no - Buuud@IRC
  314.    for some of code below */
  315. void get_term_dimensions(int *w, int *h)
  316. {
  317.    *h = 0;
  318.  
  319.    /* Get BIOS's screenwidth, this works on ALL displays. */
  320.    *w = *((int *)MK_FP(0x40, 0x4a));
  321.    
  322.    /* Use Ralf Brown test for EGA or greater */
  323.    asm mov ah, 12h
  324.    asm mov bl, 10h
  325.    asm mov bh, 0xFF  /* EGA or greater will change this */
  326.    asm int 10h
  327.    asm cmp bh, 0xFF
  328.    asm je L1
  329.     /* if EGA or compatible: Get BIOS's number of rows. */      
  330.       *h = *(char *)MK_FP(0x40, 0x84) + 1;
  331.    L1:
  332.       if (*h <= 0) *h = 25;
  333. }
  334.  
  335. int sys_chmod(char *file, int what, int *mode, short *dum1, short *dum2)
  336. {
  337.    int flag = 0, m = *mode;
  338.    (void) dum1; (void) dum2;
  339.    
  340.    file = msdos_pinhead_fix_dir (file);
  341.    
  342.    asm mov ah, 43h
  343.    asm mov al, byte ptr what
  344.    asm mov cx, m
  345.    asm push ds
  346.    asm lds dx, dword ptr file
  347.    asm int 21h
  348.    asm pop ds
  349.    asm mov m, cx
  350.    asm jnc L1
  351.    asm mov flag, ax
  352.    
  353.    /* Here if carry flag is set */
  354.    if (flag == 0x2) return(0);     /* file not found */
  355.    if (flag == 0x3) return(-2);
  356.     /* msg_error("Path does not exist."); */
  357.     /* else return (-3); */
  358.     /* sprintf(buf, "chmod: Unknown Error. %d", out.x.ax);
  359.        msg_error(buf);
  360.     */
  361.    return(-1);
  362.     
  363.    /* carry flag is 0 */
  364.    L1:
  365.    if (what == 0)
  366.      {
  367.     *mode = m;
  368.      }
  369.  
  370.    if (m & 0x10)
  371.      {
  372.     /* msg_error("File is a directory."); */
  373.     return(2);
  374.      }
  375.  
  376.    return(1);
  377. }
  378.  
  379. typedef struct Dos_DTA_Type
  380. {
  381.    unsigned char undoc[21];
  382.    unsigned char attr;
  383.    unsigned int time;
  384.    unsigned int date;
  385.    unsigned char low_size[2];
  386.    unsigned char high_size[2];
  387.    char name[13];
  388. } Dos_DTA_Type;
  389.  
  390. static Dos_DTA_Type Dos_DTA;
  391.  
  392. static void set_dta (void)
  393. {
  394.    Dos_DTA_Type *dummy = &Dos_DTA;
  395.    
  396.    asm mov ah, 0x1A
  397.    asm push ds
  398.    asm lds dx, dword ptr dummy
  399.    asm int 21h
  400.    asm pop ds
  401. }
  402.  
  403.  
  404. static int File_Attr;
  405.  
  406. #define HIDDEN 0x2
  407. #define SYSTEM 0x4
  408. #define SUBDIR 0x10
  409. #define READON 0x1
  410.  
  411. static char Found_Dir[256];
  412.  
  413. #define lcase(x) if (((x) >= 'A') && ((x) <= 'Z')) (x) |= 0x20
  414.  
  415. void dta_fixup_name(char *file)
  416. {
  417.    int dir;
  418.    char *p, name[13];
  419.  
  420.    strcpy(file, Found_Dir);
  421.    strcpy(name, Dos_DTA.name);
  422.    dir = (Dos_DTA.attr & SUBDIR);
  423.    p = name;
  424.    while (*p)
  425.      {
  426.     lcase(*p);
  427.     p++;
  428.      }
  429.    strcat(file, name);
  430.    if (dir) strcat(file, "\\");
  431. }
  432.  
  433. int sys_findfirst(char *thefile)
  434. {
  435.    char *f, the_path[256], *file, *f1;
  436.    char *pat, *fudge;
  437.    
  438.    set_dta();
  439.    File_Attr = READON | SUBDIR;
  440.  
  441.    file = expand_filename(thefile);
  442.    f1 = f = extract_file(file);
  443.    strcpy (Found_Dir, file);
  444.    
  445.    
  446.    Found_Dir[(int) (f - file)] = 0;
  447.  
  448.    strcpy(the_path, file);
  449.    
  450.    while (*f1 && (*f1 != '*')) f1++;
  451.    if (! *f1)
  452.      {
  453.     while (*f && (*f != '.')) f++;
  454.     if (*f) strcat(the_path, "*"); else strcat(the_path, "*.*");
  455.      }
  456.    pat = the_path;
  457.    
  458.    /* Something is very wrong after this returns.  
  459.     * thefile gets trashed for some reason.  Here I fudge until I figure 
  460.     *  out what is going on 
  461.     * 
  462.     * Note: This has been fixed.  I am just too lazy to remove the fudge. 
  463.     */
  464.    fudge = thefile;
  465.    
  466.    asm mov ah, 0x4e
  467.    asm mov cx, File_Attr
  468.    asm push ds
  469.    asm lds dx, dword ptr pat
  470.    asm int 21h
  471.    asm pop ds
  472.    asm jc L1 
  473.    
  474.    thefile = fudge;
  475.    
  476.    /* fprintf(stderr, "asm:%lu\t|%s|\n", thefile, thefile); */
  477.    
  478.    dta_fixup_name(file);
  479.    strcpy(thefile, file);
  480.    return(1);
  481.    L1:
  482.    return 0;
  483. }
  484.  
  485. int sys_findnext(char *file)
  486. {
  487.    asm mov ah, 0x4F
  488.    asm int 21h
  489.    asm jc L1
  490.    dta_fixup_name(file);
  491.    return(1);
  492.    L1:
  493.    return(0);
  494. }
  495.  
  496.  
  497.  
  498. #if 0
  499. unsigned long sys_file_mod_time(char *file)
  500. {
  501.    struct stat buf;
  502.    
  503.    if (stat(file, &buf) != 0) return(0);
  504.    return ((unsigned long) buf.st_mtime);
  505.    close(fd);
  506.    return ((unsigned long) buf.st_mtime);
  507.    /*
  508.    asm mov ah, 57h
  509.    asm mov al, 0
  510.    asm mov bx, fd
  511.    asm int 21h
  512.    asm mov cx, d
  513.    asm mov dx, t
  514.    close(fd);
  515.    fprintf(stderr, "Time ok.");
  516.    return(1); */
  517. }
  518. #endif
  519.  
  520. /* Here we do a find first followed by calling routine to conver time */
  521. unsigned long sys_file_mod_time(char *file)
  522. {
  523.    struct time t;
  524.    struct date d;
  525.    /* struct tm *local; */
  526.    time_t secs;
  527.    unsigned int dat, tim;
  528.    
  529.    File_Attr = READON | SUBDIR;
  530.    
  531.    set_dta();
  532.  
  533.    asm mov ah, 0x4e
  534.    asm mov cx, File_Attr
  535.    asm push ds
  536.    asm lds dx, dword ptr file
  537.    asm int 21h
  538.    asm pop ds
  539.    asm jnc A_LABEL
  540.    return 0;
  541.    
  542.    A_LABEL:
  543.    tim = Dos_DTA.time;
  544.    dat = Dos_DTA.date;
  545.    t.ti_min = (tim >> 5) & 63;
  546.    t.ti_hour = (tim >> 11) & 31;
  547.    t.ti_hund = 0;
  548.    t.ti_sec = 2 * (tim & 31);
  549.    d.da_day = dat & 31;
  550.    d.da_mon = (dat >> 5) & 15;
  551.    d.da_year = 1980 + ((dat >> 9) & 0x7F);
  552.    secs = dostounix(&d, &t);
  553.    return((unsigned long) secs);
  554. }
  555.  
  556.