/* * Copyright (C) 2007 Kevin Cody Jr. * All rights reserved. * * Note, my email systems are broken right now, I can be reached * on FreeNode IRC as user "kevincody". * * This is an early API targeted for eventual inclusion * in the G* suite of programming libraries. Permission to * distribute is granted solely for developmental and * experimental purposes to that end. * * The author offers an open binding contract, that upon completion * of the interface specification, all work will be released under * the LGPL, version is a subject for debate. Until then, however, * it is required that any further development or derivative work * be submitted back to me, and furthermore, only be circulated * within the community of developers actively working the project. * * Final public licensing must account for the licensing requirements * of glib-2 and the current ncurses library. Someone should probably * ask the EFF or whoever, but curses is part of most UNIXes one way * or another, so I can't imagine why LGPL would be a problem. * * --- * * GCurses: * * A GObject-based wrapper around the venerable curses library * for character-cell terminal manipulation. * * This class intends to expose the full functionality of curses * through a purely glib/gobject interface, while reducing the * overwhelming redundancy of the curses API. * * Note, applications using GCurses should never call curses * functions directly. GCurses manages the ncurses library state, * and direct calls will likely wind up on the wrong screen. * * Major Changes: * * * The notion of a default screen is deprecated, replaced by * a constructor that binds to the controlling terminal. * * * Character attributes (including color) and cursor position * can be controlled via GObject properties, as well as normal * set/get/etc. method calls. * * * Character set translation is organic to the object. * * * scanf and friends are omitted as being a bad idea for stack * integrity, and as being ill suited to terminal applications * * * Prefers to use 32-bit unicode internally, although legacy * byte-width output is available for 8-bit encoded strings. * * * An actual WINDOW object is always created for each SCREEN * * * Several full-screen root "WINDOW" objects can be associated * with each SCREEN, one active at any given time, thus * programatically simulating the "screen" unix utility. * */ #ifndef __G_CURSES_H__ #define __G_CURSES_H__ #include #define _XOPEN_SOURCE_EXTENDED #include G_BEGIN_DECLS /* * GObject boilerplate */ GType g_curses_get_type (void); #define G_CURSES_TYPE (g_curses_get_type ()) #define G_CURSES(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_CURSES_TYPE, GCurses)) #define G_CURSES_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), G_CURSES_TYPE, GCursesClass)) #define IS_G_CURSES(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_CURSES_TYPE)) #define IS_G_CURSES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), G_CURSES_TYPE)) #define GET_G_CURSES_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), G_CURSES_TYPE, GCursesClass)) /* * Constants */ /* Compare virtual virtual terminals to "screen" windows, but without * having a kernel pty for each window, just the one per curses SCREEN */ #define G_CURSES_MAX_VVT 10 /* This equivalence allows a single event handler */ #define G_CURSES_EVENT_NONE G_CURSES_EVENT_KEY typedef enum { G_CURSES_PROP_NONE, G_CURSES_PROP_FDES_IN, /* construct-only required */ G_CURSES_PROP_FDES_OUT, /* construct-only required */ G_CURSES_PROP_ATTR, /* read-write*/ G_CURSES_PROP_ATTR_OFF, /* write-only */ G_CURSES_PROP_ATTR_ON, /* write-only */ G_CURSES_PROP_CHAR_SET, /* read-write */ G_CURSES_PROP_CURS_VIS, /* read-write */ G_CURSES_PROP_KEYS_CBREAK, /* read-write */ G_CURSES_PROP_KEYS_DELAY, /* read-write */ G_CURSES_PROP_KEYS_ECHO, /* read-write */ G_CURSES_PROP_KEYS_KEYPAD, /* read-write */ G_CURSES_PROP_KEYS_RAW, /* read-write */ G_CURSES_PROP_TERM_CHAR, /* read-write */ G_CURSES_PROP_TERM_TYPE, /* read-write */ } GCursesProp; typedef enum { G_CURSES_ATTR_NORMAL = 0x00000000, G_CURSES_ATTR_STANDOUT = 0x00000100, G_CURSES_ATTR_UNDERLINE = 0x00000200, G_CURSES_ATTR_REVERSE = 0x00000400, G_CURSES_ATTR_BLINK = 0x00000800, G_CURSES_ATTR_DIM = 0x00001000, G_CURSES_ATTR_BOLD = 0x00002000 } GCursesAttr; typedef enum { G_CURSES_COLOR_BLACK = 0, G_CURSES_COLOR_RED = 1, G_CURSES_COLOR_GREEN = 2, G_CURSES_COLOR_YELLOW = 3, G_CURSES_COLOR_BLUE = 4, G_CURSES_COLOR_MAGENTA = 5, G_CURSES_COLOR_CYAN = 6, G_CURSES_COLOR_WHITE = 7 } GCursesColor; typedef enum { G_CURSES_CURSOR_NONE = 0, G_CURSES_CURSOR_NORMAL = 1, G_CURSES_CURSOR_BRIGHT = 2 } GCursesCursor; typedef enum { G_CURSES_EVENT_KEY = 0x00, G_CURSES_EVENT_CLICK = 0x01, G_CURSES_EVENT_DOUBLE = 0x02, G_CURSES_EVENT_TRIPLE = 0x04, G_CURSES_EVENT_ALL_CLICK = 0x07, G_CURSES_EVENT_DRAGDROP = 0x08, G_CURSES_EVENT_ALL_PRESS = 0x0F, G_CURSES_EVENT_MOVEMENT = 0x10, G_CURSES_EVENT_ALL_EVENT = 0x1F } GCursesEventType; typedef enum { G_CURSES_KEY_MOD_NONE = 0, G_CURSES_KEY_MOD_SHIFT = 1, G_CURSES_KEY_MOD_CTRL = 2, G_CURSES_KEY_MOD_ALT = 4 } GCursesKeyModifier; /* * Simple types */ typedef guint8 GCursesColorPair; /* * Event structure */ typedef struct { GCursesEventType type; GCursesKeyModifier modifier; gunichar key; /* FIXME, union, also button */ guint y; guint x; } GCursesEvent; /* * Forward instance struct declaration */ typedef struct _GCurses GCurses; /* * Callback prototype */ typedef void (*GCursesEventFunc) (GCurses *self, GCursesEvent *ev, gpointer user_data); /* * Instance structure */ struct _GCurses { GObject parent; /* constructor properties */ gint outfd; /* display file descriptor */ gint infd; /* keyboard file descriptor */ /* read-write properties */ gchar *charset; /* output stream charset */ gchar *termset; /* physical terminal charset */ gchar *termtype; /* physical terminal type */ gchar *keyset; /* physical keyboard type */ /* private members */ FILE *_outfd; /* display file handle */ FILE *_infd; /* keyboard file handle */ SCREEN *screen; /* native curses screen handle */ GIConv *gconv; /* charset translation handle */ WINDOW *win; /* currently displayed window */ WINDOW *vvt[G_CURSES_MAX_VVT]; /* see above */ GCursesEvent eventmask; GCursesEventFunc *callback; gpointer *userdata; guint size_y; guint size_x; gboolean have_cbreak; /* should use one or the */ gboolean have_raw; /* other, never both */ }; /* * Class structure */ typedef struct { GObjectClass parent; /* ncurses can only translate into the "current" charset */ gchar *current_locale; /* ncurses can only draw to the "current" screen */ SCREEN *current_screen; } GCursesClass; /* * Constructors */ /* base case constructor takes a read and write file descriptor * note these are integer fd's, not the FILE structs used by curses */ GCurses * g_curses_new_fds (gint out_fd, gint in_fd); /* wrapper to open a single bidirectional file descriptor */ static inline GCurses * g_curses_new_fd (gint fd) { return g_curses_new_fds( fd, fd ); } /* wrapper to open the controlling terminal */ static inline GCurses * g_curses_new (void) { return g_curses_new_fds( 1, 0 ); } /* * Locking Methods * * Used to make a given screen/window "active" before * performing i/o, as ncurses itself is not reentrant */ /* acquire the i/o lock */ void g_curses_acquire (GCurses *self); /* release the i/o lock */ void g_curses_release (GCurses *self); /* * Simple Unicode I/O Methods * * Also used for single-byte character modes. * Bits >= 8 forced to 0 if keypad is FALSE. */ /* print a single character */ gboolean g_curses_putch (GCurses *self, gunichar ch, GError **error); /* read a single keystroke */ gunichar g_curses_getch (GCurses *self, GError **error); /* stuff a single keystroke */ gboolean g_curses_ungetch (GCurses *self, gunichar ch, GError **error); /* * String Unicode Output Methods * * These are UCS-4, and are unaffected by the * configured stream locale. They are, however, * still translated to the actual terminal encoding. */ /* print a null-terminated unicode string */ gboolean g_curses_putustr (GCurses *self, const gunichar *str, GError **error); /* print an unterminated unicode string */ gboolean g_curses_putunstr (GCurses *self, const gunichar *str, gsize num, GError **error); /* * String Single-Byte Output Methods * * These are in the configured stream locale, which * could actually be multibyte utf-8 or somesuch. */ /* print a null-terminated string */ gboolean g_curses_putstr (GCurses *self, const gchar *str, GError **error); /* print an unterminated string */ gboolean g_curses_putnstr (GCurses *self, const gchar *str, gsize num, GError **error); /* * Character normalization methods */ /* specifies the encoding type for subsequent put* * any mismatch with the underlying terminal will be translated */ gboolean g_curses_set_charset (GCurses *self, const gchar *charset, GError **error); /* informs curses of the charset used by the terminal */ gboolean g_curses_set_termset (GCurses *self, const gchar *termset, GError **error); /* informs curses of the underlying terminal emulation */ gboolean g_curses_set_termtype (GCurses *self, const gchar *termtype, GError **error); /* informs curses of the underlying keyboard type - supported??? useful??? */ gboolean g_curses_set_keyboard (GCurses *self, const gchar *keyboard, GError **error); /* * Attribute Methods */ /* add the argument bits to the current attribute */ gboolean g_curses_attr_on (GCurses *self, GCursesAttr attr); /* remove the argument bits from the current attribute */ gboolean g_curses_attr_off (GCurses *self, GCursesAttr attr); /* set the current attribute exactly equal to the argument bits */ gboolean g_curses_attr_set (GCurses *self, GCursesAttr attr); /* query the current attribute value */ GCursesAttr g_curses_attr_get (GCurses *self); /* set the attribute value for a series of pre-displayed characters */ gboolean g_curses_attr_change (GCurses *self, GCurses attr, gsize n); /* * High-Level Color Methods */ /* sets up color map for _fore, _back, _line, _blink */ gboolean g_curses_color_init (GCurses *self); /* sets foreground color */ gboolean g_curses_color_set_fore (GCurses *self, GCursesColor f); /* sets background color */ gboolean g_curses_color_set_back (GCurses *self, GCursesColor b); /* sets blinking characters (i know...) */ gboolean g_curses_color_set_blink (GCurses *self, gboolean blink); /* sets underlined characters */ gboolean g_curses_color_set_underline (GCurses *self, gboolean uline); /* * Low-Level Color Methods */ /* sets the RGB values for a color */ gboolean g_curses_color_value_set (GCurses *self, GCursesColor color, guint16 red, guint16 green, guint16 blue); /* gets the RGB values for a color */ gboolean g_curses_color_value_get (GCurses *self, GCursesColor color, guint16 *red, guint16 *green, guint16 *blue); /* manually set up a color pair, unnecessary with _init above */ gboolean g_curses_color_pair_set (GCurses *self, GCursesColorPair pair, GCursesColor fore, GCursesColor back); /* query the fore+back values of a color pair */ gboolean g_curses_color_pair_get (GCurses *self, GCursesColorPair pair, GCursesColor *fore, GCursesColor *back); /* * Cursor Control Methods */ gboolean g_curses_cursor_getyx (GCurses *self, guint *y, guint *x); gboolean g_curses_cursor_move (GCurses *self, guint y, guint x); gboolean g_curses_cursor_set (GCurses *self, GCursesCursor state); /* * Key Management Methods */ /* for getch; -1 = blocking, 0 = nonblocking, >0 = milliseconds delay */ gboolean g_curses_set_delay_time (GCurses *self, gint delay); /* sets whether curses interprets non-ascii keys, see KEY_* in curses.h */ gboolean g_curses_set_keypad (GCurses *self, gboolean keypad); /* sets the terminal to character-at-a-time mode */ gboolean g_curses_set_cbreak (GCurses *self, gboolean cbreak); /* sets whether curses echoes the keypresses */ gboolean g_curses_set_echo (GCurses *self, gboolean echo); /* similar to cbreak, except -all- keys are seen by the application */ gboolean g_curses_set_raw (GCurses *self, gboolean raw); /* * Key/Mouse Methods */ /* only key events will be received until a set_events call */ gboolean g_curses_set_callback (GCurses *self, GCursesEventFunc func, gpointer user_data); /* key events cannot be disabled while a callback is installed * activating mouse events implies keypad(TRUE) */ gboolean g_curses_set_events (GCurses *self, GCursesEventType mask); /* returns the current event mask */ GCursesEventType g_curses_get_events (GCurses *self); /* add an event source to the default GMainLoop */ // g_curses_add_watch /* add an event source to an arbitrary GMainLoop */ // g_curses_add_watch_full /* * Capability Methods */ gboolean g_curses_has_key (GCurses *self, gint key); gboolean g_curses_has_color (GCurses *self); gboolean g_curses_has_color_set (GCurses *self); gboolean g_curses_has_insdel_char (GCurses *self); gboolean g_curses_has_insdel_line (GCurses *self); /* * Windowing Methods */ // create new subwindows // destroy an existing window // move a window // resize a window // hide/unhide a window // set the "active" window // query if a window at a given index exists /* * Screen Buffer Methods */ // save // restore // refresh // doupdate ? G_END_DECLS #endif /* __G_CURSES_H__ */