home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / EXTRA-ST / CPM-80-E / CPM-0.2 / CPM-0 / cpm-0.2 / io.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-21  |  4.5 KB  |  209 lines

  1. /*****************************************************************************/
  2. /*                                         */
  3. /*                                         */
  4. /*    CP/M emulator version 0.1                         */
  5. /*                                         */
  6. /*    written by Michael Bischoff (mbi@mo.math.nat.tu-bs.de)             */
  7. /*    June-1994                                 */
  8. /*                                         */
  9. /*    This file is distributed under the GNU COPYRIGHT             */
  10. /*    see COPYRIGHT.GNU for Copyright details                     */
  11. /*                                         */
  12. /*                                         */
  13. /*****************************************************************************/
  14. #include "cpmemu.h"
  15.  
  16. #define HAVE_RAW_IO
  17.  
  18. /* magic for character I/O */
  19. #include <unistd.h>
  20. #include <fcntl.h>
  21. #include <termios.h>
  22. #include <sys/types.h>
  23.  
  24. #ifdef HAVE_RAW_IO
  25. #include <sys/ioctl.h>
  26. #include <linux/kd.h>
  27. static int rawmode = 0;
  28. #endif
  29.  
  30. #define SWITCHMODES    /* switch between polled & sleeping */
  31. #define POLLING  1    /* conin() loops */
  32. #define SLEEPING 2    /* conin() sleeps until character found */
  33.  
  34. static int currentmode = POLLING;
  35. static int ifd, ofd;
  36.  
  37. static struct termios iold, iraw;
  38. static struct termios oold, oraw;
  39.  
  40. static void restore_modes(void) {
  41.     tcsetattr(ifd,TCSAFLUSH,&iold);
  42.     if (ifd != ofd)
  43.     tcsetattr(ofd,TCSAFLUSH,&oold);
  44. }
  45.  
  46. int setup_io(const char *tty) {
  47.     if (tty) {
  48.     ofd = ifd = open(tty, O_RDWR);
  49.     if (ofd < 0) {
  50.         fprintf(stderr, "cpm: cannot open tty %s\n", tty);
  51.         exit(1);
  52.     }
  53.     } else {
  54.     ifd = STDIN_FILENO;
  55.     ofd = STDOUT_FILENO;
  56.     }
  57.     if (tcgetattr(ifd, &iold))
  58.     return 0;        /* no chance */
  59.     iraw = iold;
  60.     iraw.c_lflag &= ~ECHO & ~ECHONL & ~ICANON & ~ISIG;
  61.     iraw.c_iflag &= ~(ICRNL | IGNCR | IXON | IXOFF);
  62.     iraw.c_cc[VMIN] = 0;    /* input: return without waiting */
  63.     iraw.c_cc[VTIME] = 0;
  64.  
  65.     if (ifd != ofd) {
  66.     if (tcgetattr(ofd, &oold))
  67.         return 0;        /* no chance */
  68.     oraw = oold;
  69.     oraw.c_oflag &= ~OPOST;
  70.     if (tcsetattr(ofd,TCSADRAIN,&oraw))
  71.         return 0;
  72.     } else
  73.     iraw.c_oflag &= ~OPOST;
  74.     /* now, register atexit function */
  75.     atexit(restore_modes);
  76.     if (tcsetattr(ifd,TCSADRAIN,&iraw))
  77.     return 0;
  78.     return 1;
  79. }
  80.  
  81. int waiting = -1;
  82.  
  83. static void poll(void) {
  84.     waiting = 0;
  85. #ifdef HAVE_RAW_IO
  86.     /* nasty undocumented stuff to prepare for tandy I memory mapped
  87.        keyboard emulation (need key release events) */
  88.     if (z80mem[4] == 0x5f && !rawmode) {
  89.     ioctl(ifd, KDSKBMODE, K_RAW);
  90.     rawmode = 1;
  91.     } else if (z80mem[4] != 0x5f && rawmode) {
  92.     ioctl(ifd, KDSKBMODE, K_XLATE);
  93.     rawmode = 0;
  94.     }
  95. #endif
  96.     if (read(ifd, &waiting, 1) < 1)
  97.     waiting = -1;
  98. }
  99.  
  100. void putch(int c) {    /* output character without postprocessing */
  101.     write(ofd, &c, 1);
  102. }
  103.  
  104. void putmes(const char *s) {
  105.     write(ofd, s, strlen(s));
  106. }
  107. void vt52(int c) {    /* simple vt52,adm3a => ANSI conversion */
  108.     static int state = 0, x, y;
  109.     char buff[32];
  110. #if 0
  111.     static FILE *log = NULL;
  112.     if (!log)
  113.     log = fopen("cpm.out", "w");
  114.     fputc(c, log);
  115. #endif
  116.     switch (state) {
  117.     case 0:
  118.     switch (c) {
  119.     case 0x7f:        /* DEL: echo BS, space, BS */
  120.         putmes("\b \b");
  121.         break;
  122.     case 0x1a:        /* adm3a clear screen */
  123.     case 0x0c:        /* vt52 clear screen */
  124.         putmes("\033[H\033[2J");
  125.         break;
  126.     case 0x1e:        /* adm3a cursor home */
  127.         putmes("\033[H");
  128.         break;
  129.     case 0x1b:
  130.         state = 1;    /* esc-prefix */
  131.         break;
  132.     case 1:
  133.         state = 2;    /* cursor motion prefix */
  134.         break;
  135.     case 2:        /* insert line */
  136.         putmes("\033[L");
  137.         break;
  138.     case 3:        /* delete line */
  139.         putmes("\033[M");
  140.         break;
  141.     case 5:        /* clear to eol */
  142.         putmes("\033[K");
  143.         break;
  144.     case 18: case 19:
  145.         break;
  146.     default:
  147.         putch(c);
  148.     }
  149.     break;
  150.     case 1:    /* esc was sent */
  151.     switch (c) {
  152.     case '=':
  153.     case 'Y':
  154.         state = 2;
  155.         break;
  156.     default:        /* some true ANSI sequence? */
  157.         state = 0;
  158.         putch(0x1b);
  159.         putch(c);
  160.     }
  161.     break;
  162.     case 2:
  163.     y = c - ' '+1;
  164.     state = 3;
  165.     break;
  166.     case 3:
  167.     x = c - ' '+1;
  168.     state = 0;
  169.     sprintf(buff, "\033[%d;%dH", y, x);
  170.     putmes(buff);
  171.     break;
  172.     } 
  173. }
  174.     
  175. int getch(void) {        /* return a character, or -1 if none ready */
  176.     if (waiting < 0) {
  177.     /* must read character from keyboard */
  178.     /* this part switches to sleeping mode */
  179.     if (currentmode == POLLING) {
  180.         iraw.c_cc[VMIN] = 1;
  181.         currentmode = SLEEPING;
  182.         tcsetattr(ifd,TCSADRAIN,&iraw);
  183.     }
  184.     poll();
  185.     }
  186.     if (waiting >= 0) {
  187.     int c;
  188.     c = waiting & 0xff;
  189.     waiting = -1;
  190.     return c;
  191.     }
  192.     return -1;
  193. }
  194.  
  195. int kbhit(void) {
  196.     if (waiting < 0) {
  197.     /* really ask keyboard */
  198.     /* this part switches to polling mode */
  199.     if (currentmode != POLLING) {
  200.         iraw.c_cc[VMIN] = 0;
  201.         currentmode = POLLING;
  202.         tcsetattr(ifd,TCSADRAIN,&iraw);
  203.     }
  204.     poll();
  205.     }
  206.     return waiting >= 0;
  207. }
  208.  
  209.