1 /*@ S-nail - a mail user agent derived from Berkeley Mail. 2 *@ Terminal attributes and state. 3 * 4 * Copyright (c) 2019 - 2020 Steffen (Daode) Nurpmeso <steffen@sdaoden.eu>. 5 * SPDX-License-Identifier: ISC 6 * 7 * Permission to use, copy, modify, and/or distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 #ifndef mx_TERMIOS_H 20 #define mx_TERMIOS_H 21 22 #include <mx/nail.h> 23 24 #define mx_HEADER 25 #include <su/code-in.h> 26 27 struct mx_termios_dimension; 28 29 enum mx_termios_cmd{ 30 /* Throw away the entire stack, and restore normal terminal state. 31 * The outermost level will be regularly shutdown, as via POP. 32 * The state_change handlers of all stack entries will be called. 33 * Further bits may not be set (this is 0) */ 34 mx_TERMIOS_CMD_RESET, 35 /* Only when HANDS_OFF is active, only by itself! */ 36 /* mx_TERMIOS_CMD_SET_PGRP = 1u,*/ 37 /* Create a (POPable) environment, as necessary change to the given mode. 38 * An environment carries the terminal mode as well as a possibly installed 39 * on_state_change hook; if such environment is reentered, the state change 40 * hook gets called to resume after the mode has been reestablished. 41 * Likewise, if it is left, it gets called to suspend first. 42 * XXX Any state change requires this, only RAW and RAW_TIMEOUT may be 43 * XXX switched back and forth on the same level (otherwise state_change 44 * XXX needs cmd argument, plus plus plus) */ 45 mx_TERMIOS_CMD_PUSH = 1u<<1, 46 /* Pop stack and restore the terminal setting active before. 47 * If a hook is installed, it will be called first. 48 * If a mode is given, debug version will assert the stack top matches. 49 * Further bits are ignored */ 50 mx_TERMIOS_CMD_POP = 1u<<2, 51 mx__TERMIOS_CMD_CTL_MASK = mx_TERMIOS_CMD_PUSH | mx_TERMIOS_CMD_POP, 52 mx_TERMIOS_CMD_NORMAL = 1u<<3, /* Normal canonical mode */ 53 mx_TERMIOS_CMD_PASSWORD = 2u<<3, /* Password input mode */ 54 mx_TERMIOS_CMD_RAW = 3u<<3, /* Raw mode, use by-(the given-)byte(s) input */ 55 mx_TERMIOS_CMD_RAW_TIMEOUT = 4u<<3, /* Raw mode, use (the given) timeout */ 56 mx_TERMIOS_CMD_HANDS_OFF = 5u<<3, /* We do not own the terminal */ 57 mx__TERMIOS_CMD_ACT_MASK = 7u<<3 58 }; 59 60 enum mx_termios_setup{ 61 mx_TERMIOS_SETUP_STARTUP, 62 mx_TERMIOS_SETUP_TERMSIZE 63 }; 64 65 enum mx_termios_state_change{ 66 mx_TERMIOS_STATE_SUSPEND = 1u<<0, /* Need to suspend terminal state */ 67 mx_TERMIOS_STATE_RESUME = 1u<<1, /* Need to resume terminal state */ 68 mx_TERMIOS_STATE_SIGNAL = 1u<<2, /* Call was caused by a signal */ 69 mx_TERMIOS_STATE_JOB_SIGNAL = 1u<<3, /* It was a job signal indeed */ 70 /* The environment is being popped. 71 * If it is still active, _STATE_SUSPEND will be set in addition. 72 * For HANDS_OFF handlers this will be called in a RESET even in already 73 * suspended state, so no _STATE_SUSPEND is set, then! */ 74 mx_TERMIOS_STATE_POP = 1u<<4 75 }; 76 77 /* tiossc is termios_state_change bitmix, cookie is user argument. 78 * signal is only meaningful when _STATE_SIGNAL is set. 79 * Return value indicates whether level shall be CMD_POPped: it is only 80 * honoured if TERMIOS_STATE_SUSPEND and TERMIOS_STATE_SIGNAL are both set. 81 * TODO This "to-pop" return will vanish in v15, we only need it due to longjmp 82 * TODO and of course it sucks since how many levels does the jump cross? 83 * TODO We do not know except when installing setjmps on each and every level, 84 * TODO but we do not; it is ok for this MUA today, but a real generic solution 85 * TODO in v15 will simply not care for signal jumps at all, they suck more */ 86 typedef boole (*mx_termios_on_state_change)(up cookie, u32 tiossc, s32 signal); 87 88 struct mx_termios_dimension{ 89 u32 tiosd_height; 90 /* .tiosd_height might be deduced via terminal speed, in which case this 91 * still is set to the real terminal height */ 92 u32 tiosd_real_height; 93 u32 tiosd_width; 94 /* .tiosd_width might be reduces deduced by one if we have no termcap 95 * support or if the terminal cannot write in the last column (without 96 * wrapping), in which case this still is set to the real terminal width */ 97 u32 tiosd_real_width; 98 }; 99 100 /* */ 101 EXPORT_DATA struct mx_termios_dimension mx_termios_dimen; 102 103 /* For long iterative output, like `list', tabulator-completion, etc., 104 * determine the screen width that should be used */ 105 #define mx_TERMIOS_WIDTH_OF_LISTS() \ 106 (mx_termios_dimen.tiosd_width - (mx_termios_dimen.tiosd_width >> 3)) 107 108 /* Installs signal handlers etc. Early! */ 109 EXPORT void mx_termios_controller_setup(enum mx_termios_setup what); 110 111 /* Install a state change hook for the current environment, 112 * which will receive cookie as its user argument. 113 * May not be used in and for the top level */ 114 EXPORT void mx_termios_on_state_change_set(mx_termios_on_state_change hdl, 115 up cookie); 116 117 /* tiosc is a bitmix of mx_termios_cmd values. 118 * For _RAW and _RAW_TIMEOUT a1 describes VMIN and VTIME, respectively, 119 * for SET_PGRP it is the PID */ 120 EXPORT boole mx_termios_cmd(u32 tiosc, uz a1); 121 #define mx_termios_cmdx(CMD) mx_termios_cmd(CMD, 0) 122 123 #include <su/code-ou.h> 124 #endif /* mx_TERMIOS_H */ 125 /* s-it-mode */ 126