#pragma implementation "Keyboard.h" #include #include static int inKgetc = 0; Keyboard *Keyboard::prim = 0; // primary keyboard Keyboard::Keyboard(FILE *f): SelectPoll(&SelectRead) { fp = f; if (!prim) { savekey = waitkey; waitkey = filbuf; prim = this; } } Keyboard::~Keyboard() { if (prim == this) { prim = 0; waitkey = savekey; } } void Keyboard::arm() { res = EOF; SelectPoll::arm(fileno(fp)); /* fprintf(stderr,"Keyboard::handler armed\n"); */ } void Keyboard::handler() { res = (*savekey)(fp); if (res != EOF) { /* fprintf(stderr,"Keyboard::savekey res = %d\n",res); */ disarm(); } } int Keyboard::filbuf(FILE *f) { if (inKgetc) { prim->arm(); int rc = SelectPoll::poll(60); if (rc < 0) return rc; if (rc == 0) return -1; /* idle */ return prim->res; } return (*prim->savekey)(f); } #include #include static FILE *curf = 0; void Kbegin(int cnt) { static char buf[64]; curf = stdin; noecho(); nonl(); cmode(cnt); /* should be 64 if ambiguous sequences */ setvbuf(curf,buf,_IOFBF,sizeof buf); initkey(); } void Kend() { fcntl(fileno(curf),F_SETFL,0); /* turn off NDELAY */ clearerr(curf); } void Kfile(FILE *f) { curf = f; } /* We really aren't supposed to look at _cnt, but I'm just trying to avoid unneccsary calls to fcntl(), OK? */ int Kready() { int rc; if (favail(curf) > 0) return 1; /* stuff already buffered */ if (feof(curf)) clearerr(curf); /* NDELAY already on */ else /* turn on NDELAY */ fcntl(fileno(curf),F_SETFL,O_NDELAY); rc = ungetc(getc(curf),curf); if (inKgetc) { fcntl(fileno(curf),F_SETFL,0); /* turn off NDELAY */ clearerr(curf); } return rc != EOF; } /* This is the only other "magic" that is not vanilla SysV. Waitkey is a hook available for programmers to arrange for routines to be called whenever we need to read more keyboard input. This implementation depends on a particular (but almost universal) implementation of getchar(). */ static int _filbuf(FILE *f) { return getc(f); } int (*waitkey)(FILE *) = _filbuf; int Kgetc() { int rc; if (feof(curf)) { fcntl(fileno(curf),F_SETFL,0); /* turn off NDELAY */ clearerr(curf); } ++inKgetc; if (!Kready()) rc = (*waitkey)(curf); else rc = getc(curf); --inKgetc; return rc; }