Annotation of researchv10no/ncurses/screen/naps.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Code for various kinds of delays.  Most of this is nonportable and
        !             3:  * requires various enhancements to the operating system, so it won't
        !             4:  * work on all systems.  It is included in curses to provide a portable
        !             5:  * interface, and so curses itself can use it for function keys.
        !             6:  */
        !             7: 
        !             8: /*     @(#) naps.c: 1.1 10/15/83       (1.10   3/6/83) */
        !             9: 
        !            10: #include "curses.ext"
        !            11: #include <signal.h>
        !            12: 
        !            13: #define NAPINTERVAL 100
        !            14: #define HZ 60
        !            15: 
        !            16: /* From early specs - this may change by 4.2BSD */
        !            17: struct _timeval {
        !            18:        long tv_sec;
        !            19:        long tv_usec;
        !            20: };
        !            21: 
        !            22: /*
        !            23:  * Delay the output for ms milliseconds.
        !            24:  * Note that this is NOT the same as a high resolution sleep.  It will
        !            25:  * cause a delay in the output but will not necessarily suspend the
        !            26:  * processor.  For applications needing to sleep for 1/10th second,
        !            27:  * this is not a usable substitute.  It causes a pause in the displayed
        !            28:  * output, for example, for the eye wink in snake.  It is disrecommended
        !            29:  * for "delay" to be much more than 1/2 second, especially at high
        !            30:  * baud rates, because of all the characters it will output.  Note
        !            31:  * that due to system delays, the actual pause could be even more.
        !            32:  * Some games won't work decently with this routine.
        !            33:  */
        !            34: delay_output(ms)
        !            35: int ms;
        !            36: {
        !            37:        extern int _outchar();          /* it's in putp.c */
        !            38: 
        !            39:        return _delay(ms*10, _outchar);
        !            40: }
        !            41: 
        !            42: /*
        !            43:  * napms.  Sleep for ms milliseconds.  We don't expect a particularly good
        !            44:  * resolution - 60ths of a second is normal, 10ths might even be good enough,
        !            45:  * but the rest of the program thinks in ms because the unit of resolution
        !            46:  * varies from system to system.  (In some countries, it's 50ths, for example.)
        !            47:  *
        !            48:  * Here are some reasonable ways to get a good nap.
        !            49:  *
        !            50:  * (1) Use the select system call in Berkeley 4.2BSD.
        !            51:  *
        !            52:  * (2) Use the 1/10th second resolution wait in the UNIX 3.0 tty driver.
        !            53:  *     It turns out this is hard to do - you need a tty line that is
        !            54:  *     always unused that you have read permission on to sleep on.
        !            55:  *
        !            56:  * (3) Install the ft (fast timer) device in your kernel.
        !            57:  *     This is a psuedo-device to which an ioctl will wait n ticks
        !            58:  *     and then send you an alarm.
        !            59:  *
        !            60:  * (4) Install the nap system call in your kernel.
        !            61:  *     This system call does a timeout for the requested number of ticks.
        !            62:  *
        !            63:  * (5) Write a routine that busy waits checking the time with ftime.
        !            64:  *     Ftime is not present on USG systems, and since this busy waits,
        !            65:  *     it will drag down response on your system.  But it works.
        !            66:  */
        !            67: #ifdef TIOCREMOTE
        !            68: /* on 4.2BSD, use select */
        !            69: napms(ms)
        !            70: int ms;
        !            71: {
        !            72:        struct _timeval t;
        !            73: 
        !            74:        /*
        !            75:         * If your 4.2BSD select still rounds up to the next higher second,
        !            76:         * you should remove this code and install the ft driver.
        !            77:         * This routine was written under the assumption that the problem
        !            78:         * would be corrected by 4.2BSD.
        !            79:         */
        !            80:        t.sec = ms/1000;
        !            81:        t.usec = 1000 * (ms % 1000);
        !            82:        select(0, 0, 0, 0, &t);
        !            83:        return OK;
        !            84: }
        !            85: #else
        !            86: /*
        !            87:  * Pause for ms milliseconds.  Convert to ticks and wait that long.
        !            88:  * Call nap, which is either defined below or a system call.
        !            89:  */
        !            90: napms(ms)
        !            91: int ms;
        !            92: {
        !            93:        int ticks;
        !            94:        int rv;
        !            95: 
        !            96:        ticks = ms / (1000 / HZ);
        !            97:        if (ticks <= 0)
        !            98:                ticks = 1;
        !            99:        rv = nap(ticks);  /* call either the code below or nap system call */
        !           100:        return rv;
        !           101: }
        !           102: #endif
        !           103: 
        !           104: #ifdef FTIOCSET
        !           105: #define HASNAP
        !           106: /*
        !           107:  * The following code is adapted from the sleep code in libc.
        !           108:  * It uses the "fast timer" device posted to USENET in Feb 1982.
        !           109:  * nap is like sleep but the units are ticks (e.g. 1/60ths of
        !           110:  * seconds in the USA).
        !           111:  */
        !           112: #include <setjmp.h>
        !           113: static jmp_buf jmp;
        !           114: static int ftfd;
        !           115: 
        !           116: /* don't call nap directly, you should call napms instead */
        !           117: static int
        !           118: nap(n)
        !           119: unsigned n;
        !           120: {
        !           121:        int napx();
        !           122:        unsigned altime;
        !           123:        int (*alsig)() = SIG_DFL;
        !           124:        char *ftname;
        !           125:        struct requestbuf {
        !           126:                short time;
        !           127:                short signo;
        !           128:        } rb;
        !           129: 
        !           130:        if (n==0)
        !           131:                return OK;
        !           132:        if (ftfd <= 0) {
        !           133:                ftname = "/dev/ft0";
        !           134:                while (ftfd <= 0 && ftname[7] <= '~') {
        !           135:                        ftfd = open(ftname, 0);
        !           136:                        if (ftfd <= 0)
        !           137:                                ftname[7] ++;
        !           138:                }
        !           139:        }
        !           140:        if (ftfd <= 0) {        /* Couldn't open a /dev/ft? */
        !           141:                sleepnap(n);
        !           142:                return ERR;
        !           143:        }
        !           144:        altime = alarm(1000);   /* time to maneuver */
        !           145:        if (setjmp(jmp)) {
        !           146:                signal(SIGALRM, alsig);
        !           147:                alarm(altime);
        !           148:                return OK;
        !           149:        }
        !           150:        if (altime) {
        !           151:                if (altime > n)
        !           152:                        altime -= n;
        !           153:                else {
        !           154:                        n = altime;
        !           155:                        altime = 1;
        !           156:                }
        !           157:        }
        !           158:        alsig = signal(SIGALRM, napx);
        !           159:        rb.time = n;
        !           160:        rb.signo = SIGALRM;
        !           161:        ioctl(ftfd, FTIOCSET, &rb);
        !           162:        for(;;)
        !           163:                pause();
        !           164:        /*NOTREACHED*/
        !           165: }
        !           166: 
        !           167: static
        !           168: napx()
        !           169: {
        !           170:        longjmp(jmp, 1);
        !           171: }
        !           172: #endif
        !           173: 
        !           174: #ifdef USG
        !           175: #ifndef HASNAP
        !           176: #define HASNAP
        !           177: #define IDLETTY "/dev/idletty"
        !           178: /*
        !           179:  * Do it with the timer in the tty driver.  Resolution is only 1/10th
        !           180:  * of a second.  Problem is, if the user types something while we're
        !           181:  * sleeping, we wake up immediately, and have no way to tell how long
        !           182:  * we should sleep again.  So we're sneaky and use a tty which we are
        !           183:  * pretty sure nobody is using.
        !           184:  *
        !           185:  * Note that we should be able to do this by setting VMIN to 100 and VTIME
        !           186:  * to the proper number of ticks.  But due to a bug in the USG tty driver
        !           187:  * (this bug was still there in 5.0) this hangs until VMIN chars are typed
        !           188:  * no matter how much time elapses.
        !           189:  *
        !           190:  * This requires some care.  If you choose a tty that is a dialup or
        !           191:  * which otherwise can show carrier, it will hang and you won't get
        !           192:  * any response from the keyboard.  You can use /dev/tty if you have
        !           193:  * no such tty, but response will feel funny as described above.
        !           194:  * To find a suitable tty, try "stty > /dev/ttyxx" for various ttyxx's
        !           195:  * that look unused.  If it hangs, you can't use it.  You might try
        !           196:  * connecting a cable to your port that raises carrier to keep it from hanging.
        !           197:  *
        !           198:  * To use this feature on USG, you must
        !           199:  *     ln /dev/ttyxx /dev/idletty,
        !           200:  * where /dev/ttyxx is one of your tty lines that is never used but
        !           201:  * won't hang on open.  Otherwise we always return ERR.
        !           202:  *
        !           203:  * THIS USG CODE IS UNSUPPORTED AND ON A USE-AT-YOUR-OWN-RISK BASIS.
        !           204:  */
        !           205: static int
        !           206: nap(ticks)
        !           207: int ticks;
        !           208: {
        !           209:        struct termio t, ot;
        !           210:        static int ttyfd;
        !           211:        int n, tenths;
        !           212:        char c;
        !           213: 
        !           214:        if (ttyfd == 0)
        !           215:                ttyfd = open(IDLETTY, 2);
        !           216:        if (ttyfd < 0) {
        !           217:                sleepnap(ticks);
        !           218:                return ERR;
        !           219:        }
        !           220:        tenths = (ticks+(HZ/10)/2) / (HZ/10); /* Round to nearest 10th second */
        !           221:        ioctl(ttyfd, TCGETA, &t);
        !           222:        ot = t;
        !           223:        t.c_lflag &= ~ICANON;
        !           224:        t.c_cc[VMIN] = 0;
        !           225:        t.c_cc[VTIME] = tenths;
        !           226:        ioctl(ttyfd, TCSETAW, &t);
        !           227:        n = read(ttyfd, &c, 1);
        !           228:        ioctl(ttyfd, TCSETAW, &ot);
        !           229:        /*
        !           230:         * Now we potentially have a character in c that somebody's going
        !           231:         * to want.  We just hope and pray they use getch, because there
        !           232:         * is no reasonable way to push it back onto the tty.
        !           233:         */
        !           234:        if (n > 0) {
        !           235:                for (n=0; SP->input_queue[n] >= 0; n++)
        !           236:                        ;
        !           237:                SP->input_queue[n++] = c;
        !           238:                SP->input_queue[n++] = -1;
        !           239:        }
        !           240:        return OK;
        !           241: }
        !           242: #endif
        !           243: #endif
        !           244: 
        !           245: /* If you have some other externally supplied nap(), add -DHASNAP to cflags */
        !           246: #ifndef HASNAP
        !           247: static int
        !           248: nap(ms)
        !           249: int ms;
        !           250: {
        !           251:        sleep((ms+999)/1000);
        !           252:        return ERR;
        !           253: }
        !           254: #endif
        !           255: 
        !           256: /*
        !           257:  * Nothing better around, so we have to simulate nap with sleep.
        !           258:  */
        !           259: static
        !           260: sleepnap(ticks)
        !           261: {
        !           262:        sleep((ticks+(HZ-1))/HZ);
        !           263: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.