Annotation of researchv10no/ncurses/screen/naps.c, revision 1.1.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.