~mirabilos/jupp/trunk

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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/*
 *	TTY interface header file
 *	Copyright
 *		(C) 1992 Joseph H. Allen
 *
 *	This file is part of JOE (Joe's Own Editor)
 */
#ifndef JUPP_TTY_H
#define JUPP_TTY_H

#ifdef EXTERN_CMD_C
__IDSTRING(rcsid_tty_h, "$MirOS: contrib/code/jupp/tty.h,v 1.16 2020/03/27 06:38:58 tg Exp $");
#endif

/* void ttopen(void);  Open the tty (attached to stdin) for use inside of JOE
 *
 * (0) Call sigjoe()
 *     There is also 'void ttopnn(void)' which does not do this step.
 *
 * (1) fflush(stdout)
 *
 * (2) Save the current state of the tty
 *
 * (3) Disable CR/LF/NL input translations,
 *     Disable all output processing,
 *     Disable echo and line editing, and
 *     Place tty in character at a time mode.
 *     (basically, disable all processing except for XON/XOFF if it's set)
 *
 * (4) Set this new tty state without loosing any typeahead (by using the
 *     proper ioctl).
 *
 * (5) Store the baud rate in the global variable 'baud'
 *
 * (6) Divide the baud rate into the constant DIVIDEND and store the result
 *     in the global variable 'upc'.  This should come out to the number
 *     of microseconds needed to send each character.  The constant 'DIVIDEND'
 *     should be chosen so that 'upc' reflects the real throughput of the
 *     tty, not the theoretical best throughput.
 *
 * (7) Create an output buffer of a size which depends on 'upc' and the
 *     constant 'TIMES'.  'TIMES' is the number of times per second JOE
 *     should check for typeahead.  Since we only check for typehead after
 *     the output buffer is flushed, 'upc' and the size of the output buffer
 *     determine how often this occurs.  So for example if 'upc'==1000 (~9600
 *     baud) and 'TIMES'==3, the output buffer size is set to 333 characters.
 *     Each time this buffer is completely flushed, 1/3 of a second will go by.
 */
void ttopen(void);
void ttopnn(void);
extern unsigned long upc;
extern unsigned baud;

#define TIMES 3
#define DIVIDEND 10000000

/* void ttclose(void);  Restore the tty back to its original mode.
 *
 * (1) ttyflsh()
 *
 * (2) Restore the original tty mode which aopen() had saved.  Do this without
 *     loosing any typeahead.
 *
 * (3) Call signrm().  There is also 'void ttyclsn(void)' which does not do
 *     the this step.
 */
void ttclose(void);
void ttclsn(void);

/* int ttgetc(void);  Flush the output and get the next character from the tty
 *
 * (1) ttflsh()
 *
 * (2) Read the next input character
 *     If the input closed, call 'ttsig' with 0 as its argument.
 *
 * (3) Clear 'have'
 */
int ttgetc(void);

/* void ttputc(char c);  Write a character to the output buffer.  If it becomes
 * full, call ttflsh()
 */
extern int obufp;
extern int obufsiz;
extern unsigned char *obuf;

#define ttputc(c) do {		\
	obuf[obufp++] = (c);	\
	if (obufp == obufsiz)	\
		ttflsh();	\
} while (/* CONSTCOND */ 0)

/* void ttputs(char *s);  Write a string to the output buffer.  Any time the
 * output buffer gets full, call ttflsh()
 */
void ttputs(unsigned char *s);

/* void ttsusp(void);  Suspend the process, or if the UNIX can't do it, call
 * ttshell(NULL)
 */
void ttsusp(void);

/* int ttflsh(void);  Flush the output buffer and check for typeahead.
 *
 * (1) write() any characters in the output buffer to the tty and then sleep
 *     for the amount of time it should take for the written characters to get
 *     to the tty.  This is so that any buffering between the editor and the
 *     tty is defeated.  If this is not done, the screen update will not be
 *     able to defer for typeahead.
 *
 *     The best way to do the sleep (possible only on systems with the
 *     setitimer call) is to set a timer for the necessary amount, write the
 *     characters to the tty, and then sleep until the timer expires.
 *
 *     If this can't be done, it's usually ok to 'write' and then to sleep for
 *     the necessary amount of time.  However, you will notice delays in the
 *     screen update if the 'write' actually takes any significant amount of
 *     time to execute (it usually takes none since all it usually does is
 *     write to an operating system output buffer).
 *
 * (2) The way we check for typeahead is to put the TTY in nonblocking mode
 *     and attempt to read a character.  If one could be read, the global
 *     variable 'have' is set to indicate that there is typeahead pending and
 *     the character is stored in a single character buffer until ttgetc
 *     is called.  If the global variable 'leave' is set, the check for
 *     typeahead is disabled.  This is so that once the program knows that it's
 *     about to exit, it doesn't eat the first character of your typeahead if
 *     ttflsh gets called.  'leave' should also be set before shell escapes and
 *     suspends.
 */
int ttflsh(void);

extern int have;
extern int leave;

/* void ttsig(int n);  Signal handler you provide.  This is called if the
 * editor gets a hangup signal, termination signal or if the input closes.
 * It is called with 'n' set to the number of the caught signal or 0 if the
 * input closed.
 */
RETSIGTYPE ttsig(int sig) __attribute__((__noreturn__));
void ttabrt(int, const char *);

/* void ttgtsz(int *x,int *y);  Get size of screen from ttsize/winsize
 * structure */
void ttgtsz(int *x, int *y);

/* You don't have to call these: ttopen/ttclose does it for you.  These
 * may be needed to make your own shell escape sequences.
 */

/* void sigjoe(void);  Set the signal handling for joe.  I.E., ignore all
 * signals the user can generate from the keyboard (SIGINT, SIGPIPE)
 * and trap the software terminate and hangup signals (SIGTERM, SIGHUP) so
 * that 'ttsig' gets called.
 */
void sigjoe(void);

/* void signrm(int inchild);  Set above signals back to their default values.
 */
void signrm(int);

/* MPX *mpxmk(int fd,int pid,
 *             void (*func)(),void *object,
 *             void (*die)(),void *dieobj,
 *            );
 *
 * Create an asynchronous input source handler for a process
 *   Child process id in 'pid'
 *   File descriptor to get input from in 'fd'
 *   Function to call with received characters in 'func'
 *   Function to call when process dies in 'die'
 *   The first arg passed to func and die is object and dieobj
 */
MPX *mpxmk(int *ptyfd, const unsigned char *cmd, unsigned char **args,
    void (*func)(B *, unsigned char *, int), void *object,
    void (*die)(B *), void *dieobj);


extern int noxon;
extern int Baud;

void tickoff(void);
void tickon(void);

#endif