* New version 2.21.999
[alpine.git] / pico / osdep / tty.c
blob7be2110085aff4f4ef6f2c8752efcedec059b42c
1 #if !defined(lint) && !defined(DOS)
2 static char rcsid[] = "$Id: tty.c 769 2007-10-24 00:15:40Z hubert@u.washington.edu $";
3 #endif
5 /*
6 * ========================================================================
7 * Copyright 2006-2007 University of Washington
8 * Copyright 2013-2018 Eduardo Chappa
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * ========================================================================
18 * Program: tty routines
21 #include <system.h>
22 #include <general.h>
24 #include "../estruct.h"
25 #include "../mode.h"
26 #include "../pico.h"
27 #include "../edef.h"
28 #include "../efunc.h"
29 #include "../keydefs.h"
31 #include "signals.h"
32 #ifndef _WINDOWS
33 #include "terminal.h"
34 #include "raw.h"
35 #include "read.h"
36 #else
37 #include "mswin.h"
38 #endif /* _WINDOWS */
40 #ifdef MOUSE
41 #include "mouse.h"
42 #endif /* MOUSE */
44 #include "tty.h"
47 #ifndef _WINDOWS
49 * ttopen - this function is called once to set up the terminal device
50 * streams. if called as pine composer, don't mess with
51 * tty modes, but set signal handlers.
53 int
54 ttopen(void)
56 if(Pmaster == NULL){
57 Raw(1);
58 #ifdef MOUSE
59 if(gmode & MDMOUSE)
60 init_mouse();
61 #endif /* MOUSE */
62 xonxoff_proc(preserve_start_stop);
65 picosigs();
67 return(1);
72 * ttclose - this function gets called just before we go back home to
73 * the command interpreter. If called as pine composer, don't
74 * worry about modes, but set signals to default, pine will
75 * rewire things as needed.
77 int
78 ttclose(void)
80 if(Pmaster){
81 signal(SIGHUP, SIG_DFL);
82 #ifdef SIGCONT
83 signal(SIGCONT, SIG_DFL);
84 #endif
85 #if defined(SIGWINCH) && defined(TIOCGWINSZ)
86 signal(SIGWINCH, SIG_DFL);
87 #endif
89 else{
90 Raw(0);
91 #ifdef MOUSE
92 end_mouse();
93 #endif
96 return(1);
101 * ttgetc - Read a character from the terminal, performing no editing
102 * and doing no echo at all.
104 * Args: return_on_intr -- Function to get a single character from stdin,
105 * recorder -- If non-NULL, function used to record keystroke.
106 * bail_handler -- Function used to bail out on read error.
108 * Returns: The character read from stdin.
109 * Return_on_intr is returned if read is interrupted.
110 * If read error, BAIL_OUT is returned unless bail_handler is
111 * non-NULL, in which case it is called (and usually it exits).
113 * If recorder is non-null, it is used to record the keystroke.
116 ttgetc(int return_on_intr, int (*recorder)(int), void (*bail_handler)(void))
118 int c;
120 switch(c = read_one_char()){
121 case READ_INTR:
122 return(return_on_intr);
124 case BAIL_OUT:
125 if(bail_handler)
126 (*bail_handler)();
127 else
128 return(BAIL_OUT);
130 default:
131 return(recorder ? (*recorder)(c) : c);
137 * Simple version of ttgetc with simple error handling
139 * Args: recorder -- If non-NULL, function used to record keystroke.
140 * bail_handler -- Function used to bail out on read error.
142 * Returns: The character read from stdin.
143 * If read error, BAIL_OUT is returned unless bail_handler is
144 * non-NULL, in which case it is called (and usually it exits).
146 * If recorder is non-null, it is used to record the keystroke.
147 * Retries if interrupted.
150 simple_ttgetc(int (*recorder)(int), void (*bail_handler)(void))
152 int res;
153 unsigned char c;
155 while((res = read(STDIN_FD, &c, 1)) <= 0)
156 if(!(res < 0 && errno == EINTR))
157 (*bail_handler)();
159 return(recorder ? (*recorder)((int)c) : (int)c);
164 * ttputc - Write a character to the display.
167 ttputc(UCS ucs)
169 unsigned char obuf[MAX(MB_LEN_MAX,32)];
170 int r, i, width = 0, outchars = 0;
171 int ret = 0;
173 if(ucs < 0x80)
174 return(putchar((unsigned char) ucs));
176 width = wcellwidth(ucs);
178 if(width < 0){
179 width = 1;
180 obuf[outchars++] = '?';
182 else{
184 * Convert the ucs into the multibyte
185 * character that corresponds to the
186 * ucs in the users locale.
188 outchars = wtomb((char *) obuf, ucs);
189 if(outchars < 0){
190 width = 1;
191 obuf[0] = '?';
192 outchars = 1;
196 for(i = 0; i < outchars; i++){
197 r = putchar(obuf[i]);
198 ret = (ret == EOF) ? EOF : r;
201 return(ret);
206 * ttflush - flush terminal buffer. Does real work where the terminal
207 * output is buffered up. A no-operation on systems where byte
208 * at a time terminal I/O is done.
211 ttflush(void)
213 return(fflush(stdout));
218 * ttresize - recompute the screen dimensions if necessary, and then
219 * adjust pico's internal buffers accordingly.
221 void
222 ttresize(void)
224 int row = -1, col = -1;
226 ttgetwinsz(&row, &col);
227 resize_pico(row, col);
233 * ttgetwinsz - set global row and column values (if we can get them)
234 * and return.
236 void
237 ttgetwinsz(int *row, int *col)
239 extern int _tlines, _tcolumns;
241 if(*row < 0)
242 *row = (_tlines > 0) ? _tlines - 1 : NROW - 1;
243 if(*col <= 0)
244 *col = (_tcolumns > 0) ? _tcolumns : NCOL;
245 #if defined(SIGWINCH) && defined(TIOCGWINSZ)
247 struct winsize win;
249 if (ioctl(0, TIOCGWINSZ, &win) == 0) { /* set to anything useful.. */
250 if(win.ws_row) /* ... the tty drivers says */
251 *row = win.ws_row - 1;
253 if(win.ws_col)
254 *col = win.ws_col;
257 signal(SIGWINCH, winch_handler); /* window size changes */
259 #endif
261 if(*col > NLINE-1)
262 *col = NLINE-1;
265 #else /* _WINDOWS */
267 #define MARGIN 8 /* size of minimim margin and */
268 #define SCRSIZ 64 /* scroll size for extended lines */
269 #define MROW 2 /* rows in menu */
271 /* internal prototypes */
272 int mswin_resize (int, int);
275 * Standard terminal interface dispatch table. Fields point to functions
276 * that operate the terminal. All these functions live in mswin.c, but
277 * this structure is defined here because it is specific to pico.
279 TERM term = {
282 MARGIN,
283 MROW,
284 ttopen,
285 NULL,
286 ttclose,
287 NULL, /* was mswin_getc, but not used? */
288 mswin_putc,
289 mswin_flush,
290 mswin_move,
291 mswin_eeol,
292 mswin_eeop,
293 mswin_beep,
294 mswin_rev
298 * This function is called once to set up the terminal device streams.
301 ttopen(void)
303 int rows, columns;
306 mswin_getscreensize (&rows, &columns);
307 term.t_nrow = rows - 1;
308 term.t_ncol = columns;
309 /* term.t_scrsiz = (columns * 2) / 3; */
312 * Do we implement optimized character insertion and deletion?
313 * o_insert() and o_delete()
315 /* inschar = delchar = FALSE; */
316 /* revexist = TRUE; dead code? */
318 mswin_setresizecallback (mswin_resize);
320 init_mouse();
322 return(1);
326 * This function gets called just before we go back home to the command
327 * interpreter.
330 ttclose(void)
332 mswin_clearresizecallback (mswin_resize);
333 return(1);
337 * Flush terminal buffer. Does real work where the terminal output is buffered
338 * up. A no-operation on systems where byte at a time terminal I/O is done.
341 ttflush(void)
343 return(1);
347 * ttresize - recompute the screen dimensions if necessary, and then
348 * adjust pico's internal buffers accordingly.
350 void
351 ttresize(void)
353 int row, col;
355 mswin_getscreensize(&row, &col);
356 resize_pico (row-1, col);
361 * mswin_resize - windows specific callback to set pico's internal tables
362 * to new screen dimensions.
365 mswin_resize(int row, int col)
367 if (wheadp)
368 resize_pico (row-1, col);
369 return (0);
372 #endif /* _WINDOWS */