exp2l: Work around a NetBSD 10.0/i386 bug.
[gnulib.git] / lib / term-style-control.h
blob5b57f75ed84a1668b7d4be57aed01d019581fbf9
1 /* Terminal control for outputting styled text to a terminal.
2 Copyright (C) 2019-2024 Free Software Foundation, Inc.
3 Written by Bruno Haible <bruno@clisp.org>, 2019.
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>. */
18 #ifndef _TERM_STYLE_CONTROL_H
19 #define _TERM_STYLE_CONTROL_H
21 /* The user of this file will define a macro 'term_style_user_data', such that
22 'struct term_style_user_data' is a user-defined struct. */
24 /* This file uses _GL_ASYNC_SAFE, HAVE_TCGETATTR. */
25 #if !_GL_CONFIG_H_INCLUDED
26 #error "Please include config.h first."
27 #endif
30 /* The amount of control to take over the underlying tty in order to avoid
31 garbled output on the screen, due to interleaved output of escape sequences
32 and output from the kernel (such as when the kernel echoes user's input
33 or when the kernel prints '^C' after the user pressed Ctrl-C). */
34 typedef enum
36 TTYCTL_AUTO = 0, /* Automatic best-possible choice. */
37 TTYCTL_NONE, /* No control.
38 Result: Garbled output can occur, and the terminal can
39 be left in any state when the program is interrupted. */
40 TTYCTL_PARTIAL, /* Signal handling.
41 Result: Garbled output can occur, but the terminal will
42 be left in the default state when the program is
43 interrupted. */
44 TTYCTL_FULL /* Signal handling and disabling echo and flush-upon-signal.
45 Result: No garbled output, and the terminal will
46 be left in the default state when the program is
47 interrupted. */
48 } ttyctl_t;
50 /* This struct contains data, used by implementation of this module.
51 You should not access the members of this struct; they may be renamed or
52 removed without notice. */
53 struct term_style_control_data
55 int volatile fd;
56 ttyctl_t volatile tty_control; /* Signal handling and tty control. */
57 #if HAVE_TCGETATTR
58 bool volatile same_as_stderr;
59 #endif
60 bool non_default_active; /* True if activate_term_non_default_mode()
61 is in effect. */
64 /* Forward declaration. */
65 struct term_style_user_data;
67 /* This struct contains function pointers. You implement these functions
68 in your application; this module invokes them when it needs to. */
69 struct term_style_controller
71 /* This function returns a pointer to the embedded
72 'struct term_style_control_data' contained in a
73 'struct term_style_user_data'. */
74 struct term_style_control_data * (*get_control_data) (struct term_style_user_data *);
76 /* This function brings the terminal's state back to the default state
77 (no styling attributes set). It is invoked when the process terminates
78 through exit(). */
79 void (*restore) (struct term_style_user_data *);
81 /* This function brings the terminal's state back to the default state
82 (no styling attributes set). It is async-safe (see gnulib-common.m4 for
83 the precise definition). It is invoked when the process receives a fatal
84 or stopping signal. */
85 _GL_ASYNC_SAFE void (*async_restore) (struct term_style_user_data *);
87 /* This function brings the terminal's state, from the default state, back
88 to the state where it has the desired attributes set. It is async-safe
89 (see gnulib-common.m4 for the precise definition). It is invoked when
90 the process receives a SIGCONT signal. */
91 _GL_ASYNC_SAFE void (*async_set_attributes_from_default) (struct term_style_user_data *);
95 #ifdef __cplusplus
96 extern "C" {
97 #endif
99 /* This module is used as follows:
100 1. You fill a 'struct term_style_controller' with function pointers.
101 You create a 'struct term_style_user_data' that contains, among other
102 members, a 'struct term_style_control_data'.
103 You will pass these two objects to all API functions below.
104 2. You call activate_term_style_controller to activate this controller.
105 Activation of the controller is the prerequisite for activating
106 the non-default mode, which in turn is the prerequisite for changing
107 the terminal's attributes.
108 When you are done with the styled output, you may deactivate the
109 controller. This is not required before exiting the program, but is
110 required before activating a different controller.
111 You cannot have more than one controller activated at the same time.
112 3. Once the controller is activated, you may turn on the non-default mode.
113 The non-default mode is the prerequisite for changing the terminal's
114 attributes. Once the terminal's attributes are in the default state
115 again, you may turn off the non-default mode again.
116 In other words:
117 - In the default mode, the terminal's attributes MUST be in the default
118 state; no styled output is possible.
119 - In the non-default mode, the terminal's attributes MAY switch among
120 the default state and other states.
121 This module exercises a certain amount of control over the terminal
122 during the non-default mode phases; see above (ttyctl_t) for details.
123 You may switch between the default and the non-default modes any number
124 of times.
125 The idea is that you switch back to the default mode before doing large
126 amounts of output of unstyled text. However, this is not a requirement:
127 You may leave the non-default mode turned on all the time until the
128 the program exits.
129 4. Once the non-default mode is activated, you may change the attributes
130 (foreground color, background color, font weight, font posture, underline
131 decoration, etc.) of the terminal. On Unix, this is typically done by
132 outputting appropriate escape sequences.
133 5. Once attributes are set, text output to the terminal will be rendered
134 with these attributes.
135 Note: You MUST return the terminal to the default state before outputting
136 a newline.
139 /* Activates a controller. The CONTROLLER and its USER_DATA controls the
140 terminal associated with FD. FD is usually STDOUT_FILENO.
141 TTY_CONTROL specifies the amount of control to take over the underlying tty.
142 The effects of this functions are undone by calling
143 deactivate_term_style_controller.
144 You cannot have more than one controller activated at the same time.
145 You must not close FD while the controller is active. */
146 extern void
147 activate_term_style_controller (const struct term_style_controller *controller,
148 struct term_style_user_data *user_data,
149 int fd, ttyctl_t tty_control);
151 /* Activates the non-default mode.
152 CONTROLLER and its USER_DATA must be a currently active controller.
153 This function fiddles with the signals of the current process and with
154 the underlying tty, to an extent described by TTY_CONTROL.
155 This function is idempotent: When you call it twice in a row, the second
156 invocation does nothing.
157 The effects of this function are undone by calling
158 deactivate_term_non_default_mode. */
159 extern void
160 activate_term_non_default_mode (const struct term_style_controller *controller,
161 struct term_style_user_data *user_data);
163 /* Deactivates the non-default mode.
164 CONTROLLER and its USER_DATA must be a currently active controller.
165 This function is idempotent: When you call it twice in a row, the second
166 invocation does nothing.
167 Before invoking this function, you must put the terminal's attributes in
168 the default state. */
169 extern void
170 deactivate_term_non_default_mode (const struct term_style_controller *controller,
171 struct term_style_user_data *user_data);
173 /* Deactivates a controller.
174 CONTROLLER and its USER_DATA must be a currently active controller.
175 Before invoking this function, you must ensure that the non-default mode
176 is deactivated. */
177 extern void
178 deactivate_term_style_controller (const struct term_style_controller *controller,
179 struct term_style_user_data *user_data);
181 #ifdef __cplusplus
183 #endif
185 #endif /* _TERM_STYLE_CONTROL_H */