/* * Cross Development System for Atari ST * Copyright (c) 1988, Memorial University of Newfoundland * * See ChangeLog for further history ++jrb * * 1.5 ERS modified for benefit of 16 bit compilers * 1.4 ERS * Changed BIOS calls into GEMDOS calls. * * 1.3 jrd * * Revision 1.2 88/02/03 22:56:30 m68k * Added unix like tty driver stuff * * Revision 1.1 88/01/29 17:31:39 m68k * Initial revision * */ #include #include #include #include #include #include #include #include #include "lib.h" #ifndef _COMPILER_H #include #endif #define iswhite(c) ((c) == ' ' || (c) == '\t') #define isvisable(c) ((unsigned char)(c) >= ' ') #define echochar(fd, c) if (__ttymode & ECHO) (void) _echochar(fd, c); else #define delchar(fd, n) if (__ttymode & ECHO) _delchar(fd, n); else extern int errno; extern int __col_pos; /* defined in write.c */ static int start_col; static char *thebuf; static int _echochar __PROTO((int fd, int c)); static void _delchar __PROTO((int fd, int n)); static int str_length __PROTO((char *p, int n)); extern unsigned int console_read_byte(int); extern void console_write_byte(int, int); extern int console_input_status(int); #ifdef __MSHORT__ int read(fd, buf, nbytes) int fd; void *buf; unsigned int nbytes; { return (int)(_read(fd, buf, (unsigned long) nbytes)); } #else asm(".stabs \"_read\",5,0,0,__read"); /* dept of clean tricks */ #endif long _read(fd, buf, n) int fd; void *buf; unsigned long n; { long rval, nbytes; long cnt = 0; char *p = buf; struct _device *dev; if(n > ((unsigned long)LONG_MAX)) { errno = EBADARG; return -1L; } nbytes = (long)n; if ((dev = _dev_fd(fd)) && dev->read) return (*dev->read)(fd, buf, nbytes); if (!isatty(fd)) { /* really cant do much about the signdness of nbytes here */ if ((rval = Fread(fd, nbytes, buf)) < 0) { errno = -rval; rval = -1; } return rval; } thebuf = buf; start_col = __col_pos; while (1) { *p = console_read_byte(fd); if (__ttymode & RAW) { if (__ttymode & ECHO) { console_write_byte(fd, *p); if (*p == '\r') __col_pos = 0; else if (isvisable(*p)) __col_pos++; } if (++cnt >= nbytes || !console_input_status(fd)) return cnt; p++; continue; } if ((__ttymode & CRMOD) && *p == '\r') *p = '\n'; if (*p == __tchars[TC_INTRC]) { /* Do the bsd thing here, i.e. flush buffers * and continue to read after the interupt */ echochar(fd, *p); p = buf; cnt = 0; raise(SIGINT); } else if (*p == __tchars[TC_QUITC]) { echochar(fd, *p); p = buf; cnt = 0; raise(SIGQUIT); } if (__ttymode & CBREAK) { if (*p == __tchars[TC_LNEXTC]) *p = console_read_byte(fd); if (__ttymode & ECHO) { if (*p == '\n' && (__ttymode & CRMOD)) { console_write_byte(fd, '\n'); console_write_byte(fd, '\r'); __col_pos = 0; } else (void) _echochar(fd, *p); } ++cnt; if (!console_input_status(fd)) return cnt; p++; } else if (*p == __tchars[TC_LNEXTC]) { if (__ttymode & ECHO) { console_write_byte(fd, '^'); console_write_byte(fd, '\b'); } *p = console_read_byte(fd); echochar(fd, *p++); cnt++; } else if (*p == __tchars[TC_EOFC]) { if (__ttymode & ECHO) { int i = _echochar(fd, *p); __col_pos -= i; while (i-- > 0) console_write_byte(fd, '\b'); } return cnt; } else if (*p == '\n' || *p == __tchars[TC_BRKC]) { if (__ttymode & ECHO) if (*p == '\n') { console_write_byte(fd, '\n'); if (__ttymode & CRMOD) { console_write_byte(fd, '\r'); __col_pos = 0; } } else (void) _echochar(fd, *p); return ++cnt; } else if ((*p == __tchars[TC_ERASE]) || (*p == __tchars[TC_ERASE])) { if (cnt) { --p; --cnt; delchar(fd, (int)cnt); } } else if (*p == __tchars[TC_KILL]) { while (--cnt >= 0) { delchar(fd, (int)cnt); p--; } cnt = 0; } else if (*p == __tchars[TC_WERASC]) { p--; while (cnt && iswhite(*p)) { --p; --cnt; delchar(fd, (int)cnt); } while (cnt && !iswhite(*p)) { --p; --cnt; delchar(fd, (int)cnt); } p++; } else if (*p == __tchars[TC_RPRNTC]) { char *s; echochar(fd, __tchars[TC_RPRNTC]); console_write_byte(fd, '\r'); console_write_byte(fd, '\n'); __col_pos = 0; start_col = 0; if (__ttymode & ECHO) for (s = buf ; s < p ; s++) echochar(fd, *s); } else { echochar(fd, *p); p++; cnt++; } if (cnt >= nbytes) return cnt; } /*NOTREACHED*/ } static int _echochar(fd, c) int fd; int c; { int len = 0; c &= 0xff; if (c < ' ') { if (c == '\t') { int i; len = ((__col_pos | 7) + 1) - __col_pos; if (__ttymode & XTABS) for (i = len ; i-- ;) console_write_byte(fd, ' '); else console_write_byte(fd, '\t'); } else { console_write_byte(fd, '^'); console_write_byte(fd, c + 0x40); len += 2; } } else if (c == 0x7f) { console_write_byte(fd, '^'); console_write_byte(fd, '?'); len += 2; } else { console_write_byte(fd, c); len++; } __col_pos += len; return len; } static void _delchar(fd, n) int fd, n; { int len = 0; char c = thebuf[n]; if ((c >= 0 && c < ' ') || c == 0x7f) { if (c == '\t') len = __col_pos - str_length(thebuf, n); else len += 2; } else len++; __col_pos -= len; while (len--) { console_write_byte(fd, '\b'); console_write_byte(fd, ' '); console_write_byte(fd, '\b'); } } static int str_length(p, n) char *p; int n; { int pos = start_col; char c; while (n--) { c = *p++; if ((c >= 0 && c < ' ') || c == 0x7f) if (c == '\t') pos = (pos | 7) + 1; else pos += 2; else pos++; } return pos; }