File: term.c

package info (click to toggle)
nyquist 3.23%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 58,064 kB
  • sloc: ansic: 74,758; lisp: 18,104; java: 10,719; cpp: 6,688; sh: 171; xml: 58; makefile: 40; python: 15
file content (136 lines) | stat: -rw-r--r-- 3,075 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/* term.c -- Routines for managing terminal I/O settings by Alan Cox.
 * From LJ 17 */

/* Thanks to Dave Cook for rescuing it */

/* CHANGE LOG
 * --------------------------------------------------------------------
 * 28Apr03  dm  include ioctl.h and declare void ctcinit();
 */


#include <termios.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>

void ctcinit(void);

/* This will be used for new terminal settings. */
static struct termios current;

/* This will hold the initial state so that we can restor it later. */
static struct termios initial;

/* Restor the termianl settings to those saved when term_init was called. */
void term_restore(void)
{
    tcsetattr(0, TCSANOW, &initial);
}

/* Clean up termianl; called on exit. */
void term_exit(void)
{
    term_restore();
}

/* Will be called when contrl-Z is pressed;
 * this correctly handles the terminal. */
void term_ctrlz(int i)
{
    signal(SIGTSTP, term_ctrlz);
    term_restore();
    kill(getpid(), SIGSTOP);
}

/* Will be called when the application is continued
 * after having been stopped. */
void term_cont(int i)
{
    signal(SIGCONT, term_cont);
    tcsetattr(0, TCSANOW, &current);
}

/* callback for SIGQUIT is different type from atexit callback */
void term_quit(int i)
{
    term_exit();
}

/* Needs to be called to initialize the terminal. */
void term_init(void)
{
    /* If stdin isn't a terminal this fails.
       But then so does tcsetattr(), so it doesn't matter. */
    tcgetattr(0, &initial);
    /* Save a copy to work with later. */
    current = initial;
    /* We _must_ clean up when we exit. */
    /* signal(SIGINT, term_exit); */
    ctcinit(); /* XLisp wants to catch ctrl C */
    signal(SIGQUIT, term_quit);
    /* Control-Z must also be handled. */
    signal(SIGTSTP, term_ctrlz);
    signal(SIGCONT, term_cont);
    atexit(term_exit);
}

/* Set character-by-character input mode. */
void term_character(void)
{
    /* One or more characters are sufficient to cause a read return. */
    current.c_cc[VMIN] = 1;
    /* No timeout; read waits forever until ready. */
    current.c_cc[VTIME] = 0;
    /* Line-by-line mode off */
    current.c_lflag &= ~ICANON;
#ifndef READ_LINE
    current.c_lflag &= ~ECHO;
#endif
    tcsetattr(0, TCSANOW, &current);
}

/* Return to line-by-line input mode. */
void term_line(void)
{
    current.c_lflag |= ICANON;
    tcsetattr(0, TCSANOW, &current);
}


#define ERROR(s)        return (perror(s), -1)

/* term_testchar -- tell whether character is ready or not,
 *
 * if ready, return it, otherwise return -2
 */
int term_testchar(void)
{
    int n;
    char c;

    if (ioctl(0, FIONREAD, &n) < 0)
        ERROR("IOgetchar");
    if (n == 0) return -2;
    switch(read(0, &c, 1)) {
      case 1:
        return c;
      case 0:
        return EOF;
      default:
        ERROR("IOgetchar-read");
    }
}


/* term_getchar -- get a character (block if necessary) */
/**/
int term_getchar(void)
{
    char c;
    int rslt = read(0, &c, 1);
    return (rslt == 1 ? c : EOF);
}