* New version 2.26
[alpine.git] / pico / osdep / tty.c
blob773eebc6fa0bf935c880495e664be3ee0971f797
1 /*
2 * ========================================================================
3 * Copyright 2006-2007 University of Washington
4 * Copyright 2013-2022 Eduardo Chappa
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * ========================================================================
14 * Program: tty routines
17 #include <system.h>
18 #include <general.h>
20 #include "../estruct.h"
21 #include "../mode.h"
22 #include "../pico.h"
23 #include "../edef.h"
24 #include "../efunc.h"
25 #include "../keydefs.h"
27 #include "signals.h"
28 #ifndef _WINDOWS
29 #include "terminal.h"
30 #include "raw.h"
31 #include "read.h"
32 #else
33 #include "mswin.h"
34 #endif /* _WINDOWS */
36 #ifdef MOUSE
37 #include "mouse.h"
38 #endif /* MOUSE */
40 #include "tty.h"
43 #ifndef _WINDOWS
45 * ttopen - this function is called once to set up the terminal device
46 * streams. if called as pine composer, don't mess with
47 * tty modes, but set signal handlers.
49 int
50 ttopen(void)
52 if(Pmaster == NULL){
53 Raw(1);
54 #ifdef MOUSE
55 if(gmode & MDMOUSE)
56 init_mouse();
57 #endif /* MOUSE */
58 xonxoff_proc(preserve_start_stop);
61 picosigs();
63 return(1);
68 * ttclose - this function gets called just before we go back home to
69 * the command interpreter. If called as pine composer, don't
70 * worry about modes, but set signals to default, pine will
71 * rewire things as needed.
73 int
74 ttclose(void)
76 if(Pmaster){
77 signal(SIGHUP, SIG_DFL);
78 #ifdef SIGCONT
79 signal(SIGCONT, SIG_DFL);
80 #endif
81 #if defined(SIGWINCH) && defined(TIOCGWINSZ)
82 signal(SIGWINCH, SIG_DFL);
83 #endif
85 else{
86 Raw(0);
87 #ifdef MOUSE
88 end_mouse();
89 #endif
92 return(1);
97 * ttgetc - Read a character from the terminal, performing no editing
98 * and doing no echo at all.
100 * Args: return_on_intr -- Function to get a single character from stdin,
101 * recorder -- If non-NULL, function used to record keystroke.
102 * bail_handler -- Function used to bail out on read error.
104 * Returns: The character read from stdin.
105 * Return_on_intr is returned if read is interrupted.
106 * If read error, BAIL_OUT is returned unless bail_handler is
107 * non-NULL, in which case it is called (and usually it exits).
109 * If recorder is non-null, it is used to record the keystroke.
112 ttgetc(int return_on_intr, int (*recorder)(int), void (*bail_handler)(void))
114 int c;
116 switch(c = read_one_char()){
117 case READ_INTR:
118 return(return_on_intr);
120 case BAIL_OUT:
121 if(bail_handler)
122 (*bail_handler)();
123 else
124 return(BAIL_OUT);
126 default:
127 return(recorder ? (*recorder)(c) : c);
133 * Simple version of ttgetc with simple error handling
135 * Args: recorder -- If non-NULL, function used to record keystroke.
136 * bail_handler -- Function used to bail out on read error.
138 * Returns: The character read from stdin.
139 * If read error, BAIL_OUT is returned unless bail_handler is
140 * non-NULL, in which case it is called (and usually it exits).
142 * If recorder is non-null, it is used to record the keystroke.
143 * Retries if interrupted.
146 simple_ttgetc(int (*recorder)(int), void (*bail_handler)(void))
148 int res;
149 unsigned char c;
151 while((res = read(STDIN_FD, &c, 1)) <= 0)
152 if(!(res < 0 && errno == EINTR))
153 (*bail_handler)();
155 return(recorder ? (*recorder)((int)c) : (int)c);
160 * ttputc - Write a character to the display.
163 ttputc(UCS ucs)
165 unsigned char obuf[MAX(MB_LEN_MAX,32)];
166 int r, i, width = 0, outchars = 0;
167 int ret = 0;
169 if(ucs < 0x80)
170 return(putchar((unsigned char) ucs));
172 width = wcellwidth(ucs);
174 if(width < 0){
175 width = 1;
176 obuf[outchars++] = '?';
178 else{
180 * Convert the ucs into the multibyte
181 * character that corresponds to the
182 * ucs in the users locale.
184 outchars = wtomb((char *) obuf, ucs);
185 if(outchars < 0){
186 width = 1;
187 obuf[0] = '?';
188 outchars = 1;
192 for(i = 0; i < outchars; i++){
193 r = putchar(obuf[i]);
194 ret = (ret == EOF) ? EOF : r;
197 return(ret);
202 * ttflush - flush terminal buffer. Does real work where the terminal
203 * output is buffered up. A no-operation on systems where byte
204 * at a time terminal I/O is done.
207 ttflush(void)
209 return(fflush(stdout));
214 * ttresize - recompute the screen dimensions if necessary, and then
215 * adjust pico's internal buffers accordingly.
217 void
218 ttresize(void)
220 int row = -1, col = -1;
222 ttgetwinsz(&row, &col);
223 resize_pico(row, col);
229 * ttgetwinsz - set global row and column values (if we can get them)
230 * and return.
232 void
233 ttgetwinsz(int *row, int *col)
235 extern int _tlines, _tcolumns;
237 if(*row < 0)
238 *row = (_tlines > 0) ? _tlines - 1 : NROW - 1;
239 if(*col <= 0)
240 *col = (_tcolumns > 0) ? _tcolumns : NCOL;
241 #if defined(SIGWINCH) && defined(TIOCGWINSZ)
243 struct winsize win;
245 if (ioctl(0, TIOCGWINSZ, &win) == 0) { /* set to anything useful.. */
246 if(win.ws_row) /* ... the tty drivers says */
247 *row = win.ws_row - 1;
249 if(win.ws_col)
250 *col = win.ws_col;
253 signal(SIGWINCH, winch_handler); /* window size changes */
255 #endif
257 if(*col > NLINE-1)
258 *col = NLINE-1;
261 #else /* _WINDOWS */
263 #define MARGIN 8 /* size of minimim margin and */
264 #define SCRSIZ 64 /* scroll size for extended lines */
265 #define MROW 2 /* rows in menu */
267 /* internal prototypes */
268 int mswin_resize (int, int);
271 * Standard terminal interface dispatch table. Fields point to functions
272 * that operate the terminal. All these functions live in mswin.c, but
273 * this structure is defined here because it is specific to pico.
275 TERM term = {
278 MARGIN,
279 MROW,
280 ttopen,
281 NULL,
282 ttclose,
283 NULL, /* was mswin_getc, but not used? */
284 mswin_putc,
285 mswin_flush,
286 mswin_move,
287 mswin_eeol,
288 mswin_eeop,
289 mswin_beep,
290 mswin_rev,
291 NULL /* no standout glitch in Windows */
295 * This function is called once to set up the terminal device streams.
298 ttopen(void)
300 int rows, columns;
303 mswin_getscreensize (&rows, &columns);
304 term.t_nrow = rows - 1;
305 term.t_ncol = columns;
306 /* term.t_scrsiz = (columns * 2) / 3; */
309 * Do we implement optimized character insertion and deletion?
310 * o_insert() and o_delete()
312 /* inschar = delchar = FALSE; */
313 /* revexist = TRUE; dead code? */
315 mswin_setresizecallback (mswin_resize);
317 init_mouse();
319 return(1);
323 * This function gets called just before we go back home to the command
324 * interpreter.
327 ttclose(void)
329 mswin_clearresizecallback (mswin_resize);
330 return(1);
334 * Flush terminal buffer. Does real work where the terminal output is buffered
335 * up. A no-operation on systems where byte at a time terminal I/O is done.
338 ttflush(void)
340 return(1);
344 * ttresize - recompute the screen dimensions if necessary, and then
345 * adjust pico's internal buffers accordingly.
347 void
348 ttresize(void)
350 int row, col;
352 mswin_getscreensize(&row, &col);
353 resize_pico (row-1, col);
358 * mswin_resize - windows specific callback to set pico's internal tables
359 * to new screen dimensions.
362 mswin_resize(int row, int col)
364 if (wheadp)
365 resize_pico (row-1, col);
366 return (0);
369 #endif /* _WINDOWS */