/* * System-dependent routines for the Atari ST. */ #include "stevie.h" #include /* * The following buffer is used to work around a bug in TOS. It appears that * unread console input can cause a crash, but only if console output is * going on. The solution is to always grab any unread input before putting * out a character. The following buffer holds any characters read in this * fashion. The problem can be easily produced because STEVIE can't yet keep * up with the normal auto-repeat rate in insert mode. */ #define IBUFSZ 128 static long inbuf[IBUFSZ]; /* buffer for unread input */ static long *inptr = inbuf; /* where to put next character */ /* * inchar() - get a character from the keyboard * * Certain special keys are mapped to values above 0x80. These mappings are * defined in keymap.h. If the key has a non-zero ascii value, it is simply * returned. Otherwise it may be a special key we want to map. * * The ST has a bug involving keyboard input that seems to occur when typing * quickly, especially typing capital letters. Sometimes a value of * 0x02540000 is read. This doesn't correspond to anything on the keyboard, * according to my documentation. My solution is to loop when any unknown key * is seen. Normally, the bell is rung to indicate the error. If the "bug" * value is seen, we ignore it completely. */ int inchar() { for (;;) { long c, *p; /* * Get the next input character, either from the input buffer or * directly from TOS. */ if (inptr != inbuf) { /* input in the buffer, use it */ c = inbuf[0]; /* * Shift everything else in the buffer down. This would be * cleaner if we used a circular buffer, but it really isn't * worth it. */ inptr--; for (p = inbuf; p < inptr; p++) *p = *(p + 1); } else c = Crawcin(); if ((c & 0xff) != 0) return ((int) c); switch ((int) (c >> 16) & 0xff) { case 0x62: return K_HELP; case 0x61: return K_UNDO; case 0x52: return K_INSERT; case 0x47: return K_HOME; case 0x48: return K_UARROW; case 0x50: return K_DARROW; case 0x4b: return K_LARROW; case 0x4d: return K_RARROW; case 0x29: return K_CGRAVE; /* control grave accent */ /* * Occurs due to a bug in TOS. */ case 0x54: break; /* * Add the function keys here later if we put in support for * macros. */ default: beep(); break; } } } /* * get_inchars - snarf away any pending console input * * If the buffer overflows, we discard what's left and ring the bell. */ static void get_inchars() { while (Cconis()) { if (inptr >= &inbuf[IBUFSZ]) { /* no room in buffer? */ Crawcin(); /* discard the input */ beep(); /* and sound the alarm */ } else *inptr++ = Crawcin(); } } void outchar(c) char c; { get_inchars(); Cconout(c); } void outstr(s) char *s; { get_inchars(); Cconws(s); } #define BGND 0 #define TEXT 3 /* * vbeep() - visual bell */ static void vbeep() { int text, bgnd; /* text and background colors */ long l; text = Setcolor(TEXT, -1); bgnd = Setcolor(BGND, -1); Setcolor(TEXT, bgnd); /* swap colors */ Setcolor(BGND, text); for (l = 0; l < 5000; l++); /* short pause */ Setcolor(TEXT, text); /* restore colors */ Setcolor(BGND, bgnd); } void beep() { if (RedrawingDisabled) return; if (P(P_VB)) vbeep(); else outchar('\007'); } /* * remove(file) - remove a file */ void remove(file) char *file; { Fdelete(file); } /* * rename(of, nf) - rename existing file 'of' to 'nf' */ void rename(of, nf) char *of, *nf; { Fdelete(nf); /* if 'nf' exists, remove it */ Frename(0, of, nf); } void windinit() { if (Getrez() == 0) Columns = 40; /* low resolution */ else Columns = 80; /* medium or high */ P(P_LI) = Rows = 25; Cursconf(1, NULL); } void windexit(r) int r; { exit(r); } void windgoto(r, c) int r, c; { outstr("\033Y"); outchar(r + 040); outchar(c + 040); } #ifndef MWC /* * System calls or library routines missing in TOS. */ void sleep(n) int n; { int k; k = Tgettime(); while (Tgettime() <= k + n); } #endif void delay() { long n; for (n = 0; n < 8000; n++); } #ifndef MWC int system(cmd) char *cmd; { char arg[1]; arg[0] = (char) 0; /* no arguments passed to the shell */ if (Pexec(0, cmd, arg, 0L) < 0) return -1; else return 0; } #endif #ifdef MEGAMAX char * strchr(s, c) char *s; int c; { do { if (*s == c) return (s); } while (*s++); return (NULL); } #endif #ifdef FOPENB FILE * fopenb(fname, mode) char *fname; char *mode; { char modestr[10]; sprintf(modestr, "b%s", mode); return fopen(fname, modestr); } #endif #ifndef MWC /* * getenv() - get a string from the environment * * Both Alcyon and Megamax are missing getenv(). This routine works for both * compilers and with the Beckemeyer and Gulam shells. With gulam, the * env_style variable should be set to either "mw" or "gu". */ char * getenv(name) char *name; { extern long _base; char *envp, *p; envp = *((char **) (_base + 0x2c)); for (; *envp; envp += strlen(envp) + 1) { if (strncmp(envp, name, strlen(name)) == 0) { p = envp + strlen(name); if (*p++ == '=') return p; } } return (char *) 0; } #endif