3 This program is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Lesser General Public
5 License (LGPL) as published by the Free Software Foundation.
7 Please refer to the COPYING file for more information.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 Copyright © 2004 Bruno T. C. de Oliveira
19 Copyright © 2006 Pierre Habouzit
22 #ifndef MADTTY_MADTTY_H
23 #define MADTTY_MADTTY_H
30 #include <sys/types.h>
34 /* Color codes: 0 = black, 1 = red, 2 = green, 3 = yellow, 4 = blue,
35 * 5 = magenta, 6 = cyan, 7 = white.
37 * An 'attribute' as used in this library means an 8-bit value that conveys
38 * a foreground color code, a background color code, and the bold
39 * and blink bits. Each cell in the virtual terminal screen is associated
40 * with an attribute that specifies its appearance. The bits of an attribute,
41 * from most significant to least significant, are
43 * bit: 7 6 5 4 3 2 1 0
44 * content: S F F F H B B B
47 * | | | `----- 3-bit background color code (0 - 7)
48 * | | `--------- blink bit (if on, text is blinking)
49 * | `------------- 3-bit foreground color code (0 - 7)
50 * `----------------- bold bit
52 * It is however recommended that you use the provided macros rather
53 * than dealing with this format directly.
55 * Sometimes we will call the 'SFFF' nibble above the 'extended
56 * foreground color code', and the 'HBBB' nibble the 'extended background
57 * color code'. So the extended color codes are just the regular
58 * color codes except that they have an additional bit (the most significant
59 * bit) indicating bold/blink.
62 /* retrieve attribute fields */
63 #define ROTE_ATTR_BG(attr) ((attr) & 0x07)
64 #define ROTE_ATTR_FG(attr) (((attr) & 0x70) >> 4)
66 /* retrieve 'extended' color codes (see above for info) */
67 #define ROTE_ATTR_XBG(attr) ((attr) & 0x0F)
68 #define ROTE_ATTR_XFG(attr) (((attr) & 0xF0) >> 4)
70 /* set attribute fields. This requires attr to be an lvalue, and it will
71 * be evaluated more than once. Use with care. */
72 #define ROTE_ATTR_MOD_BG(attr, newbg) attr &= 0xF8, attr |= (newbg)
73 #define ROTE_ATTR_MOD_FG(attr, newfg) attr &= 0x8F, attr |= ((newfg) << 4)
74 #define ROTE_ATTR_MOD_XBG(attr, newxbg) attr &= 0xF0, attr |= (newxbg)
75 #define ROTE_ATTR_MOD_XFG(attr, newxfg) attr &= 0x0F, attr |= ((newxfg) << 4)
76 #define ROTE_ATTR_MOD_BOLD(attr, boldbit) \
77 attr &= 0x7F, attr |= (boldbit)?0x80:0x00
78 #define ROTE_ATTR_MOD_BLINK(attr, blinkbit) \
79 attr &= 0xF7, attr |= (blinkbit)?0x08:0x00
81 /* these return non-zero for 'yes', zero for 'no'. Don't rely on them being
82 * any more specific than that (e.g. being exactly 1 for 'yes' or whatever). */
83 #define ROTE_ATTR_BOLD(attr) ((attr) & 0x80)
84 #define ROTE_ATTR_BLINK(attr) ((attr) & 0x08)
86 /* Represents each of the text cells in the terminal screen */
87 typedef struct RoteCell_ {
88 unsigned char ch; /* >= 32, that is, control characters are not
89 * allowed to be on the virtual screen */
91 unsigned char attr; /* a color attribute, as described previously */
94 /* Declaration of opaque rote_Term_Private structure */
95 typedef struct RoteTermPrivate_ RoteTermPrivate;
97 /* Represents a virtual terminal. You may directly access the fields
98 * of this structure, but please pay close attention to the fields
99 * marked read-only or with special usage notes. */
100 typedef struct RoteTerm_ {
101 int rows, cols; /* terminal dimensions, READ-ONLY. You
102 * can't resize the terminal by changing
103 * this (a segfault is about all you will
106 RoteCell **cells; /* matrix of cells. This
107 * matrix is indexed as cell[row][column]
108 * where 0 <= row < rows and
111 * You may freely modify the contents of
115 int crow, ccol; /* cursor coordinates. READ-ONLY. */
117 unsigned char curattr; /* current attribute, that is the attribute
118 * that will be used for newly inserted
121 pid_t childpid; /* pid of the child process running in the
122 * terminal; 0 for none. This is READ-ONLY. */
124 RoteTermPrivate *pd; /* private state data */
126 bool insert; /* insert or replace mode */
127 /* --- dirtiness flags: the following flags will be raised when the
128 * corresponding items are modified. They can only be unset by YOU
129 * (when, for example, you redraw the term or something) --- */
130 bool curpos_dirty; /* whether cursor location has changed */
131 bool *line_dirty; /* whether each row is dirty */
132 /* --- end dirtiness flags */
135 /* Creates a new virtual terminal with the given dimensions. You
136 * must destroy it with rote_vt_destroy after you are done with it.
137 * The terminal will be initially blank and the cursor will
138 * be at the top-left corner.
140 * Returns NULL on error.
142 RoteTerm *rote_vt_create(int rows, int cols);
144 /* Destroys a virtual terminal previously created with
145 * rote_vt_create. If rt == NULL, does nothing. */
146 void rote_vt_destroy(RoteTerm *rt);
148 /* Starts a forked process in the terminal. The <command> parameter
149 * is a shell command to execute (it will be interpreted by '/bin/sh -c')
150 * Returns the pid of the forked process.
152 * Some useful reminders: If you want to be notified when child processes exit,
153 * you should handle the SIGCHLD signal. If, on the other hand, you want to
154 * ignore exitting child processes, you should set the SIGCHLD handler to
155 * SIG_IGN to prevent child processes from hanging around the system as 'zombie
158 * Continuing to write to a RoteTerm whose child process has died does not
159 * accomplish a lot, but is not an error and should not cause your program
160 * to crash or block indefinitely or anything of that sort :-)
161 * If, however, you want to be tidy and inform the RoteTerm that its
162 * child has died, call rote_vt_forsake_child when appropriate.
164 * If there is an error, returns -1. Notice that passing an invalid
165 * command will not cause an error at this level: the shell will try
166 * to execute the command and will exit with status 127. You can catch
167 * that by installing a SIGCHLD handler if you want.
169 pid_t rote_vt_forkpty(RoteTerm *rt, const char *command);
171 /* Disconnects the RoteTerm from its forked child process. This function
172 * should be called when the child process dies or something of the sort.
173 * It is not strictly necessary to call this function, but it is
175 void rote_vt_forsake_child(RoteTerm *rt);
177 /* Does some data plumbing, that is, sees if the sub process has
178 * something to write to the terminal, and if so, write it. If you
179 * called rote_vt_fork to start a forked process, you must call
180 * this function regularly to update the terminal.
182 * This function will not block, that is, if there is no data to be
183 * read from the child process it will return immediately. */
184 void rote_vt_update(RoteTerm *rt);
186 /* Puts data into the terminal: if there is a forked process running,
187 * the data will be sent to it. If there is no forked process,
188 * the data will simply be injected into the terminal (as in
190 void rote_vt_write(RoteTerm *rt, const char *data, int length);
192 /* Inject data into the terminal. <data> needs NOT be 0-terminated:
193 * its length is solely determined by the <length> parameter. Please
194 * notice that this writes directly to the terminal, that is,
195 * this function does NOT send the data to the forked process
196 * running in the terminal (if any). For that, you might want
197 * to use rote_vt_write.
199 void rote_vt_inject(RoteTerm *rt, const char *data, int length);
202 /* Paints the virtual terminal screen on the given window, putting
203 * the top-left corner at the given position. The cur_set_attr
204 * function must set the curses attributes given a Rote attribute
205 * byte. It should, for example, do wattrset(win, COLOR_PAIR(n)) where
206 * n is the colorpair appropriate for the attribute and such.
208 * If you pass NULL for cur_set_attr, the default implementation will
209 * set the color pair given by (bg * 8 + 7 - fg), which seems to be
210 * a common mapping, and the bold and blink attributes will be mapped
211 * to A_BOLD and A_BLINK.
213 * At the end of the function, the cursor will be left where the virtual
214 * cursor of the terminal is supposed to be.
216 * This function does not call wrefresh(win); you have to do that yourself.
217 * This function automatically calls rote_vt_update prior to drawing
218 * so that the drawn contents are accurate.
220 void rote_vt_draw(RoteTerm *rt, WINDOW *win, int startrow, int startcol,
221 void (*cur_set_attr)(WINDOW *win, unsigned char attr));
224 /* Indicates to the terminal that the given key has been pressed.
225 * This will cause the terminal to rote_vt_write() the appropriate
226 * escape sequence for that key (that is, the escape sequence
227 * that the linux text-mode console would produce for it). The argument,
228 * keycode, must be a CURSES EXTENDED KEYCODE, the ones you get
229 * when you use keypad(somewin, TRUE) (see man page). */
230 void rote_vt_keypress(RoteTerm *rt, int keycode);
232 /* Takes a snapshot of the current contents of the terminal and
233 * saves them to a dynamically allocated buffer. Returns a pointer
234 * to the newly created buffer, which you can pass to
235 * rote_vt_restore_snapshot. Caller is responsible for free()'ing when
236 * the snapshot is no longer needed. */
237 void *rote_vt_take_snapshot(RoteTerm *rt);
239 /* Restores a snapshot previously taken with rote_vt_take_snapshot.
240 * This function does NOT free() the passed buffer */
241 void rote_vt_restore_snapshot(RoteTerm *rt, void *snapbuf);
243 /* Returns the pseudo tty descriptor associated with the given terminal.
244 * Please don't do weird things with it (like close it for instance),
245 * or things will break
247 * This function returns -1 if the given terminal does not yet have
248 * an associated pty. A pty is only associated to a terminal when
249 * needed, e.g. on a call to rote_vt_forkpty. */
250 int rote_vt_get_pty_fd(RoteTerm *rt);
252 /* Declaration of custom escape sequence callback type. See the
253 * rote_vt_add_es_handler function for more info */
254 typedef int (*rote_es_handler_t)(RoteTerm *rt, const char *es);
256 /* Installs a custom escape sequence handler for the given RoteTerm.
257 * The handler will be called by the library every time it tries to
258 * recognize an escape sequence; depending on the return value of the
259 * handler, it will proceed in a different manner. See the description
260 * of the possible return values (ROTE_HANDLERESULT_* constants) below
263 * This handler will be called EACH TIME THE ESCAPE SEQUENCE BUFFER
264 * RECEIVES A CHARACTER. Therefore, it must execute speedily in order
265 * not to create too heavy a performance penalty. In particular, the
266 * writer of the handler should take care to quickly test for invalid
267 * or incomplete escape sequences before trying to do more elaborate
270 * The handler will NOT be called with an empty escape sequence (i.e.
271 * one in which only the initial ESC was received).
273 * The custom handler receives the terminal it pertains to and the
274 * escape sequence as a string (without the initial escape character).
276 * The handler may of course modify the terminal as it sees fit, taking
277 * care not to corrupt it of course (in particular, it should appropriately
278 * raise the line_dirty[] and curpos_dirty flags to indicate what it has
281 void rote_vt_install_handler(RoteTerm *rt, rote_es_handler_t handler);
283 /* Possible return values for the custom handler function and their
285 #define ROTE_HANDLERESULT_OK 0 /* means escape sequence was handled */
287 #define ROTE_HANDLERESULT_NOTYET 1 /* means the escape sequence was not
288 * recognized yet, but there is hope that
289 * it still will once more characters
290 * arrive (i.e. it is not yet complete).
292 * The library will thus continue collecting
293 * characters and calling the handler as
294 * each character arrives until
295 * either OK or NOWAY is returned.
298 #define ROTE_HANDLERESULT_NOWAY 2 /* means the escape sequence was not
299 * recognized, and there is no chance
300 * that it will even if more characters
301 * are added to it. */
303 #endif /* MADTTY_MADTTY_H */