X-Git-Url: http://git.madism.org/?a=blobdiff_plain;f=madtty%2Fmadtty.h;fp=madtty%2Fmadtty.h;h=cd51378200079458af6c19e907ae7d13accbf90f;hb=fcbd5f6835f65055d0ac14d3a2da3afb39634fd3;hp=0000000000000000000000000000000000000000;hpb=6b8dbf88373a486ad0117331cfb577b3b6010141;p=apps%2Fmadtty.git diff --git a/madtty/madtty.h b/madtty/madtty.h new file mode 100644 index 0000000..cd51378 --- /dev/null +++ b/madtty/madtty.h @@ -0,0 +1,303 @@ +/* + LICENSE INFORMATION: + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License (LGPL) as published by the Free Software Foundation. + + Please refer to the COPYING file for more information. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Copyright © 2004 Bruno T. C. de Oliveira + Copyright © 2006 Pierre Habouzit + */ + +#ifndef MADTTY_MADTTY_H +#define MADTTY_MADTTY_H + +#ifdef USE_NCURSES +#include +#else +#include +#endif +#include +#include +#include + +/* Color codes: 0 = black, 1 = red, 2 = green, 3 = yellow, 4 = blue, + * 5 = magenta, 6 = cyan, 7 = white. + * + * An 'attribute' as used in this library means an 8-bit value that conveys + * a foreground color code, a background color code, and the bold + * and blink bits. Each cell in the virtual terminal screen is associated + * with an attribute that specifies its appearance. The bits of an attribute, + * from most significant to least significant, are + * + * bit: 7 6 5 4 3 2 1 0 + * content: S F F F H B B B + * | `-,-' | `-,-' + * | | | | + * | | | `----- 3-bit background color code (0 - 7) + * | | `--------- blink bit (if on, text is blinking) + * | `------------- 3-bit foreground color code (0 - 7) + * `----------------- bold bit + * + * It is however recommended that you use the provided macros rather + * than dealing with this format directly. + * + * Sometimes we will call the 'SFFF' nibble above the 'extended + * foreground color code', and the 'HBBB' nibble the 'extended background + * color code'. So the extended color codes are just the regular + * color codes except that they have an additional bit (the most significant + * bit) indicating bold/blink. + */ + +/* retrieve attribute fields */ +#define ROTE_ATTR_BG(attr) ((attr) & 0x07) +#define ROTE_ATTR_FG(attr) (((attr) & 0x70) >> 4) + +/* retrieve 'extended' color codes (see above for info) */ +#define ROTE_ATTR_XBG(attr) ((attr) & 0x0F) +#define ROTE_ATTR_XFG(attr) (((attr) & 0xF0) >> 4) + +/* set attribute fields. This requires attr to be an lvalue, and it will + * be evaluated more than once. Use with care. */ +#define ROTE_ATTR_MOD_BG(attr, newbg) attr &= 0xF8, attr |= (newbg) +#define ROTE_ATTR_MOD_FG(attr, newfg) attr &= 0x8F, attr |= ((newfg) << 4) +#define ROTE_ATTR_MOD_XBG(attr, newxbg) attr &= 0xF0, attr |= (newxbg) +#define ROTE_ATTR_MOD_XFG(attr, newxfg) attr &= 0x0F, attr |= ((newxfg) << 4) +#define ROTE_ATTR_MOD_BOLD(attr, boldbit) \ + attr &= 0x7F, attr |= (boldbit)?0x80:0x00 +#define ROTE_ATTR_MOD_BLINK(attr, blinkbit) \ + attr &= 0xF7, attr |= (blinkbit)?0x08:0x00 + +/* these return non-zero for 'yes', zero for 'no'. Don't rely on them being + * any more specific than that (e.g. being exactly 1 for 'yes' or whatever). */ +#define ROTE_ATTR_BOLD(attr) ((attr) & 0x80) +#define ROTE_ATTR_BLINK(attr) ((attr) & 0x08) + +/* Represents each of the text cells in the terminal screen */ +typedef struct RoteCell_ { + unsigned char ch; /* >= 32, that is, control characters are not + * allowed to be on the virtual screen */ + + unsigned char attr; /* a color attribute, as described previously */ +} RoteCell; + +/* Declaration of opaque rote_Term_Private structure */ +typedef struct RoteTermPrivate_ RoteTermPrivate; + +/* Represents a virtual terminal. You may directly access the fields + * of this structure, but please pay close attention to the fields + * marked read-only or with special usage notes. */ +typedef struct RoteTerm_ { + int rows, cols; /* terminal dimensions, READ-ONLY. You + * can't resize the terminal by changing + * this (a segfault is about all you will + * accomplish). */ + + RoteCell **cells; /* matrix of cells. This + * matrix is indexed as cell[row][column] + * where 0 <= row < rows and + * 0 <= col < cols + * + * You may freely modify the contents of + * the cells. + */ + + int crow, ccol; /* cursor coordinates. READ-ONLY. */ + + unsigned char curattr; /* current attribute, that is the attribute + * that will be used for newly inserted + * characters */ + + pid_t childpid; /* pid of the child process running in the + * terminal; 0 for none. This is READ-ONLY. */ + + RoteTermPrivate *pd; /* private state data */ + + bool insert; /* insert or replace mode */ + /* --- dirtiness flags: the following flags will be raised when the + * corresponding items are modified. They can only be unset by YOU + * (when, for example, you redraw the term or something) --- */ + bool curpos_dirty; /* whether cursor location has changed */ + bool *line_dirty; /* whether each row is dirty */ + /* --- end dirtiness flags */ +} RoteTerm; + +/* Creates a new virtual terminal with the given dimensions. You + * must destroy it with rote_vt_destroy after you are done with it. + * The terminal will be initially blank and the cursor will + * be at the top-left corner. + * + * Returns NULL on error. + */ +RoteTerm *rote_vt_create(int rows, int cols); + +/* Destroys a virtual terminal previously created with + * rote_vt_create. If rt == NULL, does nothing. */ +void rote_vt_destroy(RoteTerm *rt); + +/* Starts a forked process in the terminal. The parameter + * is a shell command to execute (it will be interpreted by '/bin/sh -c') + * Returns the pid of the forked process. + * + * Some useful reminders: If you want to be notified when child processes exit, + * you should handle the SIGCHLD signal. If, on the other hand, you want to + * ignore exitting child processes, you should set the SIGCHLD handler to + * SIG_IGN to prevent child processes from hanging around the system as 'zombie + * processes'. + * + * Continuing to write to a RoteTerm whose child process has died does not + * accomplish a lot, but is not an error and should not cause your program + * to crash or block indefinitely or anything of that sort :-) + * If, however, you want to be tidy and inform the RoteTerm that its + * child has died, call rote_vt_forsake_child when appropriate. + * + * If there is an error, returns -1. Notice that passing an invalid + * command will not cause an error at this level: the shell will try + * to execute the command and will exit with status 127. You can catch + * that by installing a SIGCHLD handler if you want. + */ +pid_t rote_vt_forkpty(RoteTerm *rt, const char *command); + +/* Disconnects the RoteTerm from its forked child process. This function + * should be called when the child process dies or something of the sort. + * It is not strictly necessary to call this function, but it is + * certainly tidy. */ +void rote_vt_forsake_child(RoteTerm *rt); + +/* Does some data plumbing, that is, sees if the sub process has + * something to write to the terminal, and if so, write it. If you + * called rote_vt_fork to start a forked process, you must call + * this function regularly to update the terminal. + * + * This function will not block, that is, if there is no data to be + * read from the child process it will return immediately. */ +void rote_vt_update(RoteTerm *rt); + +/* Puts data into the terminal: if there is a forked process running, + * the data will be sent to it. If there is no forked process, + * the data will simply be injected into the terminal (as in + * rote_vt_inject) */ +void rote_vt_write(RoteTerm *rt, const char *data, int length); + +/* Inject data into the terminal. needs NOT be 0-terminated: + * its length is solely determined by the parameter. Please + * notice that this writes directly to the terminal, that is, + * this function does NOT send the data to the forked process + * running in the terminal (if any). For that, you might want + * to use rote_vt_write. + */ +void rote_vt_inject(RoteTerm *rt, const char *data, int length); + +#ifdef USE_NCURSES +/* Paints the virtual terminal screen on the given window, putting + * the top-left corner at the given position. The cur_set_attr + * function must set the curses attributes given a Rote attribute + * byte. It should, for example, do wattrset(win, COLOR_PAIR(n)) where + * n is the colorpair appropriate for the attribute and such. + * + * If you pass NULL for cur_set_attr, the default implementation will + * set the color pair given by (bg * 8 + 7 - fg), which seems to be + * a common mapping, and the bold and blink attributes will be mapped + * to A_BOLD and A_BLINK. + * + * At the end of the function, the cursor will be left where the virtual + * cursor of the terminal is supposed to be. + * + * This function does not call wrefresh(win); you have to do that yourself. + * This function automatically calls rote_vt_update prior to drawing + * so that the drawn contents are accurate. + */ +void rote_vt_draw(RoteTerm *rt, WINDOW *win, int startrow, int startcol, + void (*cur_set_attr)(WINDOW *win, unsigned char attr)); + +#endif +/* Indicates to the terminal that the given key has been pressed. + * This will cause the terminal to rote_vt_write() the appropriate + * escape sequence for that key (that is, the escape sequence + * that the linux text-mode console would produce for it). The argument, + * keycode, must be a CURSES EXTENDED KEYCODE, the ones you get + * when you use keypad(somewin, TRUE) (see man page). */ +void rote_vt_keypress(RoteTerm *rt, int keycode); + +/* Takes a snapshot of the current contents of the terminal and + * saves them to a dynamically allocated buffer. Returns a pointer + * to the newly created buffer, which you can pass to + * rote_vt_restore_snapshot. Caller is responsible for free()'ing when + * the snapshot is no longer needed. */ +void *rote_vt_take_snapshot(RoteTerm *rt); + +/* Restores a snapshot previously taken with rote_vt_take_snapshot. + * This function does NOT free() the passed buffer */ +void rote_vt_restore_snapshot(RoteTerm *rt, void *snapbuf); + +/* Returns the pseudo tty descriptor associated with the given terminal. + * Please don't do weird things with it (like close it for instance), + * or things will break + * + * This function returns -1 if the given terminal does not yet have + * an associated pty. A pty is only associated to a terminal when + * needed, e.g. on a call to rote_vt_forkpty. */ +int rote_vt_get_pty_fd(RoteTerm *rt); + +/* Declaration of custom escape sequence callback type. See the + * rote_vt_add_es_handler function for more info */ +typedef int (*rote_es_handler_t)(RoteTerm *rt, const char *es); + +/* Installs a custom escape sequence handler for the given RoteTerm. + * The handler will be called by the library every time it tries to + * recognize an escape sequence; depending on the return value of the + * handler, it will proceed in a different manner. See the description + * of the possible return values (ROTE_HANDLERESULT_* constants) below + * for more info. + * + * This handler will be called EACH TIME THE ESCAPE SEQUENCE BUFFER + * RECEIVES A CHARACTER. Therefore, it must execute speedily in order + * not to create too heavy a performance penalty. In particular, the + * writer of the handler should take care to quickly test for invalid + * or incomplete escape sequences before trying to do more elaborate + * parsing. + * + * The handler will NOT be called with an empty escape sequence (i.e. + * one in which only the initial ESC was received). + * + * The custom handler receives the terminal it pertains to and the + * escape sequence as a string (without the initial escape character). + * + * The handler may of course modify the terminal as it sees fit, taking + * care not to corrupt it of course (in particular, it should appropriately + * raise the line_dirty[] and curpos_dirty flags to indicate what it has + * changed). + */ +void rote_vt_install_handler(RoteTerm *rt, rote_es_handler_t handler); + +/* Possible return values for the custom handler function and their + * meanings: */ +#define ROTE_HANDLERESULT_OK 0 /* means escape sequence was handled */ + +#define ROTE_HANDLERESULT_NOTYET 1 /* means the escape sequence was not + * recognized yet, but there is hope that + * it still will once more characters + * arrive (i.e. it is not yet complete). + * + * The library will thus continue collecting + * characters and calling the handler as + * each character arrives until + * either OK or NOWAY is returned. + */ + +#define ROTE_HANDLERESULT_NOWAY 2 /* means the escape sequence was not + * recognized, and there is no chance + * that it will even if more characters + * are added to it. */ + +#endif /* MADTTY_MADTTY_H */