diff --git a/gb.ncurses/src/Makefile.am b/gb.ncurses/src/Makefile.am index 22b7777fc..77578b992 100644 --- a/gb.ncurses/src/Makefile.am +++ b/gb.ncurses/src/Makefile.am @@ -12,5 +12,7 @@ gb_ncurses_la_SOURCES = \ main.h main.c \ c_ncurses.h c_ncurses.c \ c_window.h c_window.c \ - c_key.h c_key.c + c_key.h c_key.c \ + c_color.h c_color.c \ + c_screen.h c_screen.c diff --git a/gb.ncurses/src/c_color.c b/gb.ncurses/src/c_color.c new file mode 100644 index 000000000..98932dfa8 --- /dev/null +++ b/gb.ncurses/src/c_color.c @@ -0,0 +1,260 @@ +/* + * c_color.c - gb.ncurses Color static class + * + * Copyright (C) 2012 Tobias Boege + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * 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 General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#define __C_COLOR_C + +#include + +#include "../gambas.h" + +#include "main.h" +#include "c_color.h" + +static int _index; +static int _color; + +void COLOR_init() +{ + /* TODO: use_default_colors() and assume_default_colors() for more control */ + start_color(); +} + +static int COLOR_setpair(short index, short fg, short bg) +{ + init_pair(index, fg, bg); + return 0; +} + +static int COLOR_content(short color, short *r, short *g, short *b) +{ + short ar, ag, ab; + + color_content(color, r ? r : &ar, g ? g : &ag, b ? b : &ab); + return 0; +} + +/* + * Color static class + */ + +BEGIN_PROPERTY(Color_Capabilities) + + RETURN_SELF(); + +END_PROPERTY + +BEGIN_PROPERTY(Color_Colors) + + GB.ReturnInteger(COLORS); + +END_PROPERTY + +BEGIN_PROPERTY(Color_Pairs) + + GB.ReturnInteger(COLOR_PAIRS); + +END_PROPERTY + +BEGIN_METHOD(Color_get, GB_INTEGER index) + + if (!PAIR_VALID(VARG(index))) + { + GB.Error(GB_ERR_BOUND); + return; + } + _index = VARG(index); + RETURN_SELF(); + +END_METHOD + +BEGIN_METHOD(Color_Define, GB_INTEGER color; GB_INTEGER r; GB_INTEGER g; GB_INTEGER b) + + if (!COLOR_VALID(VARG(color))) + { + GB.Error(GB_ERR_BOUND); + return; + } + init_color(VARG(color), VARG(r), VARG(g), VARG(b)); + +END_METHOD + +BEGIN_METHOD(Color_Content, GB_INTEGER color) + + if (!COLOR_VALID(VARG(color))) + { + GB.Error(GB_ERR_BOUND); + return; + } + _color = VARG(color); + RETURN_SELF(); + +END_METHOD + +/* + * .Color.Capabilities virtual class + */ + +BEGIN_PROPERTY(ColorCapabilities_Change) + + GB.ReturnBoolean(can_change_color()); + +END_PROPERTY + +BEGIN_PROPERTY(ColorCapabilities_Color) + + GB.ReturnBoolean(has_colors()); + +END_PROPERTY + +/* + * .Color.Pair virtual class + */ + +BEGIN_PROPERTY(ColorPair_Background) + + short f, b; + + pair_content(_index, &f, &b); + if (READ_PROPERTY) + { + GB.ReturnInteger(b); + return; + } + if (!COLOR_VALID(VPROP(GB_INTEGER))) + { + GB.Error(GB_ERR_BOUND); + return; + } + b = VPROP(GB_INTEGER); + COLOR_setpair(_index, f, b); + + +END_PROPERTY + +BEGIN_PROPERTY(ColorPair_Foreground) + + short f, b; + + pair_content(_index, &f, &b); + if (READ_PROPERTY) + { + GB.ReturnInteger(f); + return; + } + if (!COLOR_VALID(VPROP(GB_INTEGER))) + { + GB.Error(GB_ERR_BOUND); + return; + } + f = VPROP(GB_INTEGER); + COLOR_setpair(_index, f, b); + +END_PROPERTY + +/* + * .Color.Content virtual class + */ + +BEGIN_PROPERTY(ColorContent_Red) + + short red; + + COLOR_content(_color, &red, NULL, NULL); + GB.ReturnInteger(red); + +END_PROPERTY + +BEGIN_PROPERTY(ColorContent_Green) + + short green; + + COLOR_content(_color, NULL, &green, NULL); + GB.ReturnInteger(green); + +END_PROPERTY + +BEGIN_PROPERTY(ColorContent_Blue) + + short blue; + + COLOR_content(_color, NULL, NULL, &blue); + GB.ReturnInteger(blue); + +END_PROPERTY + +GB_DESC CColorDesc[] = +{ + GB_DECLARE("Color", 0), + GB_NOT_CREATABLE(), + + GB_CONSTANT("Black", "i", COLOR_BLACK), + GB_CONSTANT("Red", "i", COLOR_RED), + GB_CONSTANT("Green", "i", COLOR_GREEN), + GB_CONSTANT("Yellow", "i", COLOR_YELLOW), + GB_CONSTANT("Blue", "i", COLOR_BLUE), + GB_CONSTANT("Magenta", "i", COLOR_MAGENTA), + GB_CONSTANT("Cyan", "i", COLOR_CYAN), + GB_CONSTANT("White", "i", COLOR_WHITE), + + GB_STATIC_PROPERTY_READ("Capabilities", ".Color.Capabilities", Color_Capabilities), + GB_STATIC_PROPERTY_READ("Colors", "i", Color_Colors), + GB_STATIC_PROPERTY_READ("Pairs", "i", Color_Pairs), + + GB_STATIC_METHOD("_get", ".Color.Pair", Color_get, "(Index)i"), + GB_STATIC_METHOD("Define", NULL, Color_Define, "(Color)i(R)i(G)i(B)i"), + GB_STATIC_METHOD("Content", ".Color.Content", Color_Content, "(Color)i"), + + GB_END_DECLARE +}; + +GB_DESC CColorCapabilitiesDesc[] = +{ + GB_DECLARE(".Color.Capabilities", 0), + GB_VIRTUAL_CLASS(), + + GB_STATIC_PROPERTY_READ("Color", "b", ColorCapabilities_Color), + GB_STATIC_PROPERTY_READ("Change", "b", ColorCapabilities_Change), + + GB_END_DECLARE +}; + +GB_DESC CColorPairDesc[] = +{ + GB_DECLARE(".Color.Pair", 0), + GB_VIRTUAL_CLASS(), + + GB_STATIC_PROPERTY("Background", "i", ColorPair_Background), + GB_STATIC_PROPERTY("Foreground", "i", ColorPair_Foreground), + + GB_END_DECLARE +}; + +GB_DESC CColorContentDesc[] = +{ + GB_DECLARE(".Color.Content", 0), + GB_VIRTUAL_CLASS(), + + GB_STATIC_PROPERTY_READ("Red", "i", ColorContent_Red), + GB_STATIC_PROPERTY_READ("Green", "i", ColorContent_Green), + GB_STATIC_PROPERTY_READ("Blue", "i", ColorContent_Blue), + + GB_END_DECLARE +}; diff --git a/gb.ncurses/src/c_color.h b/gb.ncurses/src/c_color.h new file mode 100644 index 000000000..69449cca1 --- /dev/null +++ b/gb.ncurses/src/c_color.h @@ -0,0 +1,18 @@ +#ifndef __C_COLOR_H +#define __C_COLOR_H + +#include + +#define PAIR_VALID(p) (p > 0 && p < COLOR_PAIRS) +#define COLOR_VALID(c) (c >= 0 && c < COLORS) + +#ifndef __C_COLOR_C +extern GB_DESC CColorDesc[]; +extern GB_DESC CColorCapabilitiesDesc[]; +extern GB_DESC CColorPairDesc[]; +extern GB_DESC CColorContentDesc[]; +#endif + +void COLOR_init(); + +#endif /* __C_COLOR_H */ diff --git a/gb.ncurses/src/c_key.c b/gb.ncurses/src/c_key.c index ea6b46cc0..1a6902634 100644 --- a/gb.ncurses/src/c_key.c +++ b/gb.ncurses/src/c_key.c @@ -21,12 +21,19 @@ #define __C_KEY_C -#include "../gambas.h" - #include +#include "../gambas.h" + +#include "main.h" #include "c_key.h" +BEGIN_METHOD(Key_get, GB_STRING key) + + GB.ReturnInteger((int) *STRING(key)); + +END_METHOD + GB_DESC CKeyDesc[] = { GB_DECLARE("Key", 0), @@ -48,18 +55,20 @@ GB_DESC CKeyDesc[] = GB_CONSTANT("Down", "i", KEY_DOWN), /* F keys */ - GB_CONSTANT("F1", "i", KEY_F(0)), - GB_CONSTANT("F2", "i", KEY_F(1)), - GB_CONSTANT("F3", "i", KEY_F(2)), - GB_CONSTANT("F4", "i", KEY_F(3)), - GB_CONSTANT("F5", "i", KEY_F(4)), - GB_CONSTANT("F6", "i", KEY_F(5)), - GB_CONSTANT("F7", "i", KEY_F(6)), - GB_CONSTANT("F8", "i", KEY_F(7)), - GB_CONSTANT("F9", "i", KEY_F(8)), - GB_CONSTANT("F10", "i", KEY_F(9)), - GB_CONSTANT("F11", "i", KEY_F(10)), - GB_CONSTANT("F12", "i", KEY_F(11)), + GB_CONSTANT("F1", "i", KEY_F(1)), + GB_CONSTANT("F2", "i", KEY_F(2)), + GB_CONSTANT("F3", "i", KEY_F(3)), + GB_CONSTANT("F4", "i", KEY_F(4)), + GB_CONSTANT("F5", "i", KEY_F(5)), + GB_CONSTANT("F6", "i", KEY_F(6)), + GB_CONSTANT("F7", "i", KEY_F(7)), + GB_CONSTANT("F8", "i", KEY_F(8)), + GB_CONSTANT("F9", "i", KEY_F(9)), + GB_CONSTANT("F10", "i", KEY_F(10)), + GB_CONSTANT("F11", "i", KEY_F(11)), + GB_CONSTANT("F12", "i", KEY_F(12)), + + GB_STATIC_METHOD("_get", "i", Key_get, "(Key)s"), GB_END_DECLARE }; diff --git a/gb.ncurses/src/c_ncurses.c b/gb.ncurses/src/c_ncurses.c index 6c08c3aac..d5ff13e00 100644 --- a/gb.ncurses/src/c_ncurses.c +++ b/gb.ncurses/src/c_ncurses.c @@ -27,40 +27,11 @@ #include #include "c_ncurses.h" +#include "c_color.h" +#include "c_screen.h" #include "main.h" #define E_END "Could not end ncurses" -#define E_UNSUPP "Unsupported value" - -#define CURSOR_HIDDEN 0 -#define CURSOR_VISIBLE 1 - -#define INPUT_COOKED 0 -#define INPUT_CBREAK 1 -#define INPUT_RAW 2 - -static bool nc_cursor; -static int nc_input; -static int nc_echo; - -DECLARE_EVENT(EVENT_Resize); - -#if 0 -/* - * Signal handler for the SIGWINCH signal. - * @signum: signal number given - * This routine dispatches the Resize Event - */ -void nc_sigwinch_handler(int signum) -{ - /* TODO: I wonder if this works... */ - - /* BM: Of course not! :-) You can't raise an event from a signal handler - * and moreover you have no sender! */ - - if (signum == SIGWINCH) GB.Raise(NULL, EVENT_Resize, 0); -} -#endif static bool _init = FALSE; @@ -77,26 +48,10 @@ void NCURSES_init(void) initscr(); keypad(stdscr, TRUE); - /* global variable default setup */ - nc_cursor = CURSOR_VISIBLE; - nc_input = INPUT_CBREAK; - nc_echo = 0; - /* accordingly... */ - curs_set(1); - cbreak(); - noecho(); - -#if 0 - struct sigaction sa; - - sa.sa_handler = nc_sigwinch_handler; - sigemptyset(&(sa.sa_mask)); - sa.sa_flags = 0; - if (sigaction(SIGWINCH, &sa, NULL) == -1) - { - fprintf(stderr, "gb.ncurses: Could not install SIGWINCH signal handler"); - } -#endif + /* Color setup */ + COLOR_init(); /* Color._init() would be called before the main hook, apparently */ + /* Screen setup */ + SCREEN_init(); refresh(); @@ -112,85 +67,6 @@ void NCURSES_exit() } } - -BEGIN_PROPERTY(NCurses_Cursor) - - if (READ_PROPERTY) - { - GB.ReturnInteger(nc_cursor); - return; - } - - switch (VPROP(GB_INTEGER)) - { - case CURSOR_HIDDEN: - curs_set(0); - break; - case CURSOR_VISIBLE: - curs_set(1); - break; - default: - GB.Error(E_UNSUPP); - return; - } - nc_cursor = VPROP(GB_INTEGER); - -END_PROPERTY - -BEGIN_PROPERTY(NCurses_Input) - - if (READ_PROPERTY) - { - GB.ReturnInteger(nc_input); - return; - } - - switch (VPROP(GB_INTEGER)) - { - case INPUT_COOKED: - noraw(); - nocbreak(); - break; - case INPUT_CBREAK: - cbreak(); - break; - case INPUT_RAW: - raw(); - break; - default: - GB.Error(E_UNSUPP); - return; - } - nc_input = VPROP(GB_INTEGER); - -END_PROPERTY - -BEGIN_PROPERTY(NCurses_Echo) - - if (READ_PROPERTY) - { - GB.ReturnBoolean(nc_echo); - return; - } - - nc_echo = VPROP(GB_BOOLEAN); - if (nc_echo) echo(); - else noecho(); - -END_PROPERTY - -BEGIN_PROPERTY(NCurses_Lines) - - GB.ReturnInteger(LINES); - -END_PROPERTY - -BEGIN_PROPERTY(NCurses_Cols) - - GB.ReturnInteger(COLS); - -END_PROPERTY - BEGIN_METHOD_VOID(NCurses_exit) NCURSES_exit(); @@ -202,19 +78,6 @@ GB_DESC CNCursesDesc[] = GB_DECLARE("NCurses", 0), GB_NOT_CREATABLE(), - GB_CONSTANT("Hidden", "i", CURSOR_HIDDEN), - GB_CONSTANT("Visible", "i", CURSOR_VISIBLE), - - GB_CONSTANT("Cooked", "i", INPUT_COOKED), - GB_CONSTANT("CBreak", "i", INPUT_CBREAK), - GB_CONSTANT("Raw", "i", INPUT_RAW), - - GB_STATIC_PROPERTY("Cursor", "i", NCurses_Cursor), - GB_STATIC_PROPERTY("Input", "i", NCurses_Input), - GB_STATIC_PROPERTY("Echo", "b", NCurses_Echo), - - GB_STATIC_PROPERTY_READ("Lines", "i", NCurses_Lines), - GB_STATIC_PROPERTY_READ("Cols", "i", NCurses_Cols), GB_STATIC_METHOD("_exit", NULL, NCurses_exit, NULL), diff --git a/gb.ncurses/src/c_ncurses.h b/gb.ncurses/src/c_ncurses.h index 8bcf082d5..bbb6d68de 100644 --- a/gb.ncurses/src/c_ncurses.h +++ b/gb.ncurses/src/c_ncurses.h @@ -25,7 +25,6 @@ #include #include "gambas.h" -#include "gb_common.h" #define NCURSES_RUNNING NCURSES_running() diff --git a/gb.ncurses/src/c_screen.c b/gb.ncurses/src/c_screen.c new file mode 100644 index 000000000..3b132136a --- /dev/null +++ b/gb.ncurses/src/c_screen.c @@ -0,0 +1,198 @@ +/* + * c_screen.c - gb.ncurses Screen class + * + * Copyright (C) 2012 Tobias Boege + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * 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 General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#define __C_SCREEN_C + +#include +#include + +#include + +#include "gambas.h" + +#include "c_screen.h" +#include "main.h" + +#define E_UNSUPP "Unsupported value" + +#define CURSOR_HIDDEN 0 +#define CURSOR_VISIBLE 1 + +#define INPUT_COOKED 0 +#define INPUT_CBREAK 1 +#define INPUT_RAW 2 + +static bool _cursor; +static int _input; +static int _echo; + +DECLARE_EVENT(EVENT_Resize); + +#if 0 +/* + * Signal handler for the SIGWINCH signal. + * @signum: signal number given + * This routine dispatches the Resize Event + */ +void nc_sigwinch_handler(int signum) +{ + /* TODO: I wonder if this works... */ + + /* BM: Of course not! :-) You can't raise an event from a signal handler + * and moreover you have no sender! */ + + if (signum == SIGWINCH) GB.Raise(NULL, EVENT_Resize, 0); +} +#endif + +int SCREEN_init() +{ + /* Global variable default setup */ + _cursor = CURSOR_VISIBLE; + _input = INPUT_CBREAK; + _echo = 0; + /* accordingly... */ + curs_set(1); + cbreak(); + noecho(); + +#if 0 + struct sigaction sa; + + sa.sa_handler = nc_sigwinch_handler; + sigemptyset(&(sa.sa_mask)); + sa.sa_flags = 0; + if (sigaction(SIGWINCH, &sa, NULL) == -1) + { + fprintf(stderr, "gb.ncurses: Could not install SIGWINCH signal handler"); + } +#endif + + return 0; +} + +BEGIN_PROPERTY(Screen_Cursor) + + if (READ_PROPERTY) + { + GB.ReturnInteger(_cursor); + return; + } + + switch (VPROP(GB_INTEGER)) + { + case CURSOR_HIDDEN: + curs_set(0); + break; + case CURSOR_VISIBLE: + curs_set(1); + break; + default: + GB.Error(E_UNSUPP); + return; + } + _cursor = VPROP(GB_INTEGER); + +END_PROPERTY + +BEGIN_PROPERTY(Screen_Input) + + if (READ_PROPERTY) + { + GB.ReturnInteger(_input); + return; + } + + switch (VPROP(GB_INTEGER)) + { + case INPUT_COOKED: + noraw(); + nocbreak(); + break; + case INPUT_CBREAK: + cbreak(); + break; + case INPUT_RAW: + raw(); + break; + default: + GB.Error(E_UNSUPP); + return; + } + _input = VPROP(GB_INTEGER); + +END_PROPERTY + +BEGIN_PROPERTY(Screen_Echo) + + if (READ_PROPERTY) + { + GB.ReturnBoolean(_echo); + return; + } + + _echo = VPROP(GB_BOOLEAN); + if (_echo) echo(); + else noecho(); + +END_PROPERTY + +BEGIN_PROPERTY(Screen_Lines) + + GB.ReturnInteger(LINES); + +END_PROPERTY + +BEGIN_PROPERTY(Screen_Cols) + + GB.ReturnInteger(COLS); + +END_PROPERTY + +BEGIN_METHOD_VOID(Screen_new) + + SCREEN_init(); + +END_METHOD + +GB_DESC CScreenDesc[] = +{ + GB_DECLARE("Screen", 0), //sizeof(struct nc_screen)), + GB_AUTO_CREATABLE(), + + GB_CONSTANT("Hidden", "i", CURSOR_HIDDEN), + GB_CONSTANT("Visible", "i", CURSOR_VISIBLE), + + GB_CONSTANT("Cooked", "i", INPUT_COOKED), + GB_CONSTANT("CBreak", "i", INPUT_CBREAK), + GB_CONSTANT("Raw", "i", INPUT_RAW), + + GB_STATIC_PROPERTY("Cursor", "i", Screen_Cursor), + GB_STATIC_PROPERTY("Input", "i", Screen_Input), + GB_STATIC_PROPERTY("Echo", "b", Screen_Echo), + + GB_STATIC_PROPERTY_READ("Lines", "i", Screen_Lines), //GB_PROPERTY + GB_STATIC_PROPERTY_READ("Cols", "i", Screen_Cols), + + GB_METHOD("_new", NULL, Screen_new, NULL), + + GB_END_DECLARE +}; diff --git a/gb.ncurses/src/c_screen.h b/gb.ncurses/src/c_screen.h new file mode 100644 index 000000000..c7b7b5a2d --- /dev/null +++ b/gb.ncurses/src/c_screen.h @@ -0,0 +1,33 @@ +/* + * c_screen.h - gb.ncurses Screen class + * + * Copyright (C) 2012 Tobias Boege + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * 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 General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#ifndef __C_SCREEN_H +#define __C_SCREEN_H + +#include "gambas.h" + +#ifndef __C_WINDOW_C +extern GB_DESC CScreenDesc[]; +#endif + +int SCREEN_init(); + +#endif /* __C_SCREEN_H */ diff --git a/gb.ncurses/src/c_window.c b/gb.ncurses/src/c_window.c index 1d6f5cd45..378ab6b83 100644 --- a/gb.ncurses/src/c_window.c +++ b/gb.ncurses/src/c_window.c @@ -32,12 +32,10 @@ #include "main.h" #include "c_window.h" +#include "c_color.h" /* The nc_window currently having the focus (raising Read events) */ -static CWINDOW *focused = NULL; - -#define MAIN (THIS ? THIS->main : stdscr) -#define CONTENT (THIS ? THIS->content : stdscr) +static struct nc_window *focused = NULL; DECLARE_EVENT(EVENT_Read); @@ -179,6 +177,7 @@ static int WINDOW_copy_window(WINDOW *src, WINDOW *dst, int sx, int sy, int nx, int i, j; chtype *chbuf; /* We ought to have a separate buffer in case @src and @dst overlap */ int dattrs = getattrs(dst); + int ox, oy; MAKE_COORDS(src, sx, sy); MAKE_COORDS(dst, dx, dy); @@ -195,10 +194,13 @@ static int WINDOW_copy_window(WINDOW *src, WINDOW *dst, int sx, int sy, int nx, } GB.Alloc((void **) &chbuf, nx * ny * sizeof(chtype)); + getyx(src, oy, ox); for (i = 0; i < ny; i++) for (j = 0; j < nx; j++) chbuf[i * nx + j] = mvwinch(src, sy + i, sx + j); + wmove(src, oy, ox); + getyx(dst, oy, ox); wattrset(dst, A_NORMAL); for (i = 0; i < ny; i++) { @@ -208,6 +210,7 @@ static int WINDOW_copy_window(WINDOW *src, WINDOW *dst, int sx, int sy, int nx, waddch(dst, chbuf[i * nx + j]); } wattrset(dst, dattrs); + wmove(dst, oy, ox); GB.Free((void **) &chbuf); return 0; } @@ -218,15 +221,15 @@ static int WINDOW_copy_window(WINDOW *src, WINDOW *dst, int sx, int sy, int nx, */ static int WINDOW_remove(void *_object) { - wclear(CONTENT); + wclear(THIS->content); if (HAS_BORDER) { - delwin(CONTENT); - wclear(MAIN); + delwin(THIS->content); + wclear(THIS->main); } REFRESH(); del_panel(THIS->pan); - delwin(MAIN); + delwin(THIS->main); return 0; } @@ -266,7 +269,7 @@ static int WINDOW_remove_content(void *_object) WINDOW_content_to_main(); wattrset(THIS->main, getattrs(THIS->content)); delwin(THIS->content); - THIS->content = MAIN; + THIS->content = THIS->main; return 0; } @@ -278,13 +281,19 @@ static int WINDOW_remove_content(void *_object) static int WINDOW_draw_border(void *_object, bool b) { /* TODO: how to check for the possibility of displaying ACS chars? - terminfo exports the 'acsc' variable but i couldn't find - the format of that string */ - //WINDOW_print(THIS, tigetstr("acsc"), -1, -1); + Terminfo exports the 'eacs' variable. Anyone to tell whether I understood the bare + information correctly? */ if (b) - box(MAIN, 0, 0); + { + if (tigetstr("enacs")) + box(THIS->main, 0, 0); + else + wborder(THIS->main, '|', '|', '-', '-', '+', '+', '+', '+'); + } else - wborder(MAIN, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '); + { + wborder(THIS->main, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '); + } return 0; } @@ -297,14 +306,14 @@ static int WINDOW_draw_border(void *_object, bool b) */ static int WINDOW_cursor_move(void *_object, int x, int y) { - MAKE_COORDS(CONTENT, x, y); - if (BAD_COORDS(CONTENT, x, y)) + MAKE_COORDS(THIS->content, x, y); + if (BAD_COORDS(THIS->content, x, y)) { GB.Error(E_COORDS); return -1; } - if (wmove(CONTENT, y, x) == ERR) + if (wmove(THIS->content, y, x) == ERR) { GB.Error("Could not move cursor"); return -1; @@ -322,7 +331,7 @@ static int WINDOW_move(void *_object, int x, int y) { int ox, oy; - getbegyx(MAIN, oy, ox); + getbegyx(THIS->main, oy, ox); if (x == -1) x = ox; if (y == -1) @@ -336,7 +345,7 @@ static int WINDOW_move(void *_object, int x, int y) move_panel(THIS->pan, y, x); if (HAS_BORDER) { - mvwin(CONTENT, y + 1, x + 1); + mvwin(THIS->content, y + 1, x + 1); WINDOW_draw_border(THIS, 1); } return 0; @@ -355,7 +364,7 @@ static int WINDOW_resize(void *_object, int w, int h) { int ow, oh; - getmaxyx(CONTENT, ow, oh); + getmaxyx(THIS->content, oh, ow); if (w == -1) w = ow; if (h == -1) @@ -371,7 +380,7 @@ static int WINDOW_resize(void *_object, int w, int h) } WINDOW_draw_border(THIS, 0); - wresize(MAIN, h + 2, w + 2); + wresize(THIS->main, h + 2, w + 2); } if (w <= 0 || w > COLS || h <= 0 || h > LINES) @@ -379,8 +388,8 @@ static int WINDOW_resize(void *_object, int w, int h) GB.Error(E_DIMENSION); return -1; } - wresize(CONTENT, h, w) == ERR; - replace_panel(THIS->pan, MAIN); + wresize(THIS->content, h, w); + replace_panel(THIS->pan, THIS->main); if (HAS_BORDER) WINDOW_draw_border(THIS, 1); @@ -399,24 +408,27 @@ static int WINDOW_resize(void *_object, int w, int h) */ static int WINDOW_print(void *_object, char *str, int x, int y) { - int width, len; - char *p; + int width; + char *p, *q; p = str; do { if (WINDOW_cursor_move(THIS, x, y) == -1) return -1; - width = getmaxx(CONTENT) - x; - if ((len = strlen(p)) < width) - width = len; - waddnstr(CONTENT, p, width); + width = getmaxx(THIS->content) - x; + width = MIN(width, strlen(p)); + if ((q = strchr(p, '\n'))) + width = MIN(width, q - p); + waddnstr(THIS->content, p, width); p += width; - if (THIS && !THIS->wrap) + if (*p == '\n') + p++; + if (!THIS->wrap) break; x = 0; y++; - if (y >= getmaxy(CONTENT)) + if (y >= getmaxy(THIS->content)) break; } while (*p); @@ -456,28 +468,28 @@ int WINDOW_insert(void *_object, char *str, int x, int y) } /* we need the real vals, WINDOW_cursor_move() interpreted the -1 values for us */ - x = getcurx(CONTENT); - y = getcury(CONTENT); + x = getcurx(THIS->content); + y = getcury(THIS->content); if (rec == 1) /* first call, initialise all static control data */ { - XY2A(CONTENT, getmaxx(CONTENT) - 1, getmaxy(CONTENT) - 1, a); + XY2A(THIS->content, getmaxx(THIS->content) - 1, getmaxy(THIS->content) - 1, a); a += strlen(str); - A2XY(CONTENT, a, ex, ey); + A2XY(THIS->content, a, ex, ey); /* the text may fill the entire box, so we better catch that and locate the cursor at the end in that case */ - if (ey >= getmaxy(CONTENT)) + if (ey >= getmaxy(THIS->content)) { - ex = getmaxx(CONTENT) - 1; - ey = getmaxy(CONTENT) - 1; + ex = getmaxx(THIS->content) - 1; + ey = getmaxy(THIS->content) - 1; } } /* if we're on the last line, nothing will be wrapped around at all, so we take this branch. in this case, the call works exactly like the non-wrapping insert and begins to unroll the recursion. */ - if (!THIS->wrap || y == getmaxy(CONTENT) - 1) + if (!THIS->wrap || y == getmaxy(THIS->content) - 1) { - mvwinsstr(CONTENT, y, x, str); + mvwinsstr(THIS->content, y, x, str); } else { @@ -493,21 +505,21 @@ int WINDOW_insert(void *_object, char *str, int x, int y) } /* if the @str itself overflows the line, there will be a remainder of it that has to preceed the shifted string to be wrapped to the next line */ - if (x + len > getmaxx(CONTENT)) + if (x + len > getmaxx(THIS->content)) { - len = getmaxx(CONTENT) - x; + len = getmaxx(THIS->content) - x; strcpy(temp, str + len); - winstr(CONTENT, temp + strlen(temp)); + winstr(THIS->content, temp + strlen(temp)); } else { /* remainder on the right (giving a negative @n to winnstr() family seems broken in my library and may be elsewhere (manpages say it's an extension to XSI curses) */ - mvwinstr(CONTENT, y, getmaxx(CONTENT) - len, temp); + mvwinstr(THIS->content, y, getmaxx(THIS->content) - len, temp); } /* the winnstr() family of functions used to extract shifted characters moves the cursor, we have to reset it here (would have been nice to leave that fact in the manpages...) */ - mvwinsstr(CONTENT, y, x, str); + mvwinsstr(THIS->content, y, x, str); strcpy(shifted, temp); WINDOW_insert(THIS, shifted, 0, y + 1); } @@ -551,23 +563,23 @@ static int WINDOW_insert(void *_object, char *str, int x, int y) return -1; if (!THIS->wrap) { - winsstr(CONTENT, str); + winsstr(THIS->content, str); return 0; } - x = getcurx(CONTENT); - y = getcury(CONTENT); - XY2A(CONTENT, x, y, a); + x = getcurx(THIS->content); + y = getcury(THIS->content); + XY2A(THIS->content, x, y, a); len = strlen(str); - slen = getmaxy(CONTENT) * getmaxx(CONTENT) - a - len + 1; + slen = getmaxy(THIS->content) * getmaxx(THIS->content) - a - len + 1; GB.Alloc((void **) &ins, len * sizeof(chtype)); for (i = 0; i < len; i++) - ins[i] = (chtype) str[i] | getattrs(CONTENT); - WINDOW_get_mem(CONTENT, &shifted, x, y, getmaxy(CONTENT) * getmaxx(CONTENT) - a); + ins[i] = (chtype) str[i] | getattrs(THIS->content); + WINDOW_get_mem(THIS->content, &shifted, x, y, getmaxy(THIS->content) * getmaxx(THIS->content) - a); - WINDOW_put_mem(ins, CONTENT, x, y, len); - getyx(CONTENT, y, x); - WINDOW_put_mem(shifted, CONTENT, x, y, slen); + WINDOW_put_mem(ins, THIS->content, x, y, len); + getyx(THIS->content, y, x); + WINDOW_put_mem(shifted, THIS->content, x, y, slen); /* place the cursor after the last inserted char */ WINDOW_cursor_move(THIS, x, y); @@ -594,10 +606,10 @@ static int WINDOW_get_str(void *_object, int x, int y, unsigned int len, char ** char *buf; if (len == -1) - len = getmaxx(CONTENT) - getcurx(CONTENT); + len = getmaxx(THIS->content) - getcurx(THIS->content); GB.Alloc((void **) &buf, len + 1); - WINDOW_get_mem(CONTENT, &chbuf, x, y, len); + WINDOW_get_mem(THIS->content, &chbuf, x, y, len); for (i = 0; i < len; i++) buf[i] = chbuf[i] & A_CHARTEXT; buf[len] = 0; @@ -624,7 +636,7 @@ static int WINDOW_key_timeout(void *_object, int timeout, int *ret) { /* Had a timeout, the manual doesn't define any errors to happen for wgetch() besides NULL pointer arguments. The only source of ERR is timeout expired. */ - if (timeout >= 0) + if (timeout >= 0) *ret = 0; } @@ -717,7 +729,7 @@ static int WINDOW_import(void *_object, WINDOW *imp) /* Clean up former members */ if (HAS_BORDER) WINDOW_remove_content(THIS); - if (MAIN) + if (THIS->main) WINDOW_remove(THIS); THIS->main = imp; @@ -742,12 +754,13 @@ static int WINDOW_attrs_driver(void *_object, int attr, int req) switch (req) { case ATTR_DRV_RET: - return getattrs(CONTENT); + return getattrs(THIS->content); + case ATTR_DRV_COL: case ATTR_DRV_ON: - wattron(CONTENT, attr); + wattron(THIS->content, attr); break; case ATTR_DRV_OFF: - wattroff(CONTENT, attr); + wattroff(THIS->content, attr); } return 0; } @@ -766,30 +779,26 @@ static int WINDOW_char_attrs_driver(void *_object, int attr, int x, int y, int r int ox, oy; int res; chtype ch; - unsigned int mask, shift; /* unsigned in case A_COLOR has its MSB set */ - /* I wonder if everybody searched and hacked around to find that color stuff... */ - /* Find the number of bits to right-shift to get the color number from chtype - attributes - _portably_ (don't know if it is required, if anyone could point - to the magical manpage where all that is written?) */ - mask = ~(int)A_COLOR; - for (shift = 0; mask & 1; shift++, mask >>= 1); + /* Wish the attribute shift stuff was documented... + For posterity: It's all in */ - getyx(CONTENT, oy, ox); + getyx(THIS->content, oy, ox); WINDOW_cursor_move(THIS, x, y); - ch = winch(CONTENT); + ch = winch(THIS->content); switch (req) { case ATTR_DRV_RET: - /* A_ATTRIBUTES inherits A_COLOR (at least on my setup... I really - hate undocument facts as they may be no facts) */ res = ch & A_ATTRIBUTES; goto _cleanup; case ATTR_DRV_ON: - wchgat(CONTENT, 1, (ch & A_ATTRIBUTES) | attr, (ch & A_COLOR) >> shift, NULL); + wchgat(THIS->content, 1, (ch & A_ATTRIBUTES) | attr, PAIR_NUMBER(ch), NULL); break; case ATTR_DRV_OFF: - wchgat(CONTENT, 1, (ch & A_ATTRIBUTES) & ~attr, (ch & A_COLOR) >> shift, NULL); + wchgat(THIS->content, 1, (ch & A_ATTRIBUTES) & ~attr, PAIR_NUMBER(ch), NULL); + break; + case ATTR_DRV_COL: + wchgat(THIS->content, 1, (ch & A_ATTRIBUTES), PAIR_NUMBER(attr), NULL); } res = 0; @@ -817,7 +826,7 @@ END_PROPERTY BEGIN_PROPERTY(Window_Border) bool b; - int x, y; + int x, y, w, h; if (READ_PROPERTY) { @@ -830,25 +839,27 @@ BEGIN_PROPERTY(Window_Border) if (b == THIS->border) return; - /* FIXME: try Full() and then Border = True */ if (b) { - WINDOW_resize(THIS, getmaxx(CONTENT) + 2, getmaxy(CONTENT) + 2); - WINDOW_move(THIS, (x = getbegx(MAIN) - 1) == -1 ? 0 : x, - (y = getbegy(MAIN) - 1) == -1 ? 0 : y); + WINDOW_resize(THIS, (w = getmaxx(THIS->main) + 2) > COLS ? getmaxx(THIS->main) : w, + (h = getmaxy(THIS->main) + 2) > LINES ? getmaxy(THIS->main) : h); + WINDOW_move(THIS, (x = getbegx(THIS->main) - 1) < 0 ? 0 : x, + (y = getbegy(THIS->main) - 1) < 0 ? 0 : y); WINDOW_add_content(THIS); WINDOW_draw_border(THIS, 1); } else { - /* FIXME: routine logic */ - /* FIXME: try Border = False if the window is Full() */ WINDOW_draw_border(THIS, 0); + /* as long as we have control over the area taken up (before resize), we shall erase + the whole border */ + REAL_REFRESH(); WINDOW_remove_content(THIS); - THIS->border = b; /* FIXME: this is important here due to the automatic border-redraw in WINDOW_resize */ - WINDOW_resize(THIS, getmaxx(CONTENT) - 2, getmaxy(CONTENT) - 2); - WINDOW_move(THIS, (x = getbegx(MAIN) + 1) >= getmaxx(MAIN) ? getmaxx(MAIN) - 1 : x, - (y = getbegy(MAIN) + 1) >= getmaxy(MAIN) ? getmaxy(MAIN) - 1 : y); + /* since HAS_BORDER is still TRUE, resize and move would draw a new border, we prevent this */ + THIS->border = 0; + WINDOW_resize(THIS, getmaxx(THIS->content) - 2, getmaxy(THIS->content) - 2); + WINDOW_move(THIS, (x = getbegx(THIS->main) + 1) >= getmaxx(THIS->main) ? getmaxx(THIS->main) - 1 : x, + (y = getbegy(THIS->main) + 1) >= getmaxy(THIS->main) ? getmaxy(THIS->main) - 1 : y); } THIS->border = b; REFRESH(); @@ -866,15 +877,15 @@ BEGIN_PROPERTY(Window_Buffered) END_PROPERTY -BEGIN_PROPERTY(Window_ClientHeight) +BEGIN_PROPERTY(Window_ContainerHeight) - GB.ReturnInteger(getmaxy(MAIN)); + GB.ReturnInteger(getmaxy(THIS->main)); END_PROPERTY -BEGIN_PROPERTY(Window_ClientWidth) +BEGIN_PROPERTY(Window_ContainerWidth) - GB.ReturnInteger(getmaxx(MAIN)); + GB.ReturnInteger(getmaxx(THIS->main)); END_PROPERTY @@ -882,7 +893,7 @@ BEGIN_PROPERTY(Window_CursorX) if (READ_PROPERTY) { - GB.ReturnInteger(getcurx(CONTENT)); + GB.ReturnInteger(getcurx(THIS->content)); return; } WINDOW_cursor_move(THIS, VPROP(GB_INTEGER), -1); @@ -894,7 +905,7 @@ BEGIN_PROPERTY(Window_CursorY) if (READ_PROPERTY) { - GB.ReturnInteger(getcury(CONTENT)); + GB.ReturnInteger(getcury(THIS->content)); return; } WINDOW_cursor_move(THIS, -1, VPROP(GB_INTEGER)); @@ -912,7 +923,7 @@ BEGIN_PROPERTY(Window_Height) if (READ_PROPERTY) { - GB.ReturnInteger(getmaxy(CONTENT)); + GB.ReturnInteger(getmaxy(THIS->content)); return; } WINDOW_resize(THIS, -1, VPROP(GB_INTEGER)); @@ -936,7 +947,7 @@ BEGIN_PROPERTY(Window_Width) if (READ_PROPERTY) { - GB.ReturnInteger(getmaxx(CONTENT)); + GB.ReturnInteger(getmaxx(THIS->content)); return; } WINDOW_resize(THIS, VPROP(GB_INTEGER), -1); @@ -948,7 +959,7 @@ BEGIN_PROPERTY(Window_X) if (READ_PROPERTY) { - GB.ReturnInteger(getbegx(MAIN)); + GB.ReturnInteger(getbegx(THIS->main)); return; } WINDOW_move(THIS, VPROP(GB_INTEGER), -1); @@ -960,7 +971,7 @@ BEGIN_PROPERTY(Window_Y) if (READ_PROPERTY) { - GB.ReturnInteger(getbegy(MAIN)); + GB.ReturnInteger(getbegy(THIS->main)); return; } WINDOW_move(THIS, -1, VPROP(GB_INTEGER)); @@ -977,9 +988,13 @@ BEGIN_METHOD(Window_new, GB_INTEGER x; GB_INTEGER y; GB_INTEGER w; GB_INTEGER h) GB.Error("Not in NCurses mode"); return; } - new = newwin(VARG(h), VARG(w), VARG(y), VARG(x)); + new = newwin(MISSING(h) ? LINES : VARG(h), MISSING(w) ? COLS : VARG(w), + MISSING(y) ? 0 : VARG(y), MISSING(x) ? 0 : VARG(x)); WINDOW_import(THIS, new); + if (!GB.Parent(_object)) + GB.Attach(THIS, (void *) GB.Application.StartupClass(), "Window"); + REFRESH(); END_METHOD @@ -989,7 +1004,8 @@ BEGIN_METHOD_VOID(Window_free) WINDOW_remove(THIS); if (focused == THIS) GB.Watch(0, GB_WATCH_NONE, NULL, 0); - /* the REFRESH() makes use of THIS so it would be unwise to call it + GB.Detach(THIS); + /* the REFRESH() makes use of THIS so it would be unwise to call that since we just invalidated it */ REAL_REFRESH(); @@ -1013,7 +1029,7 @@ BEGIN_METHOD(Window_Ask, GB_STRING opts; GB_INTEGER tries) if (!miss) t = VARG(tries); else - t = -1; /* just to silence the compiler */ + t = -1; /* to silence the compiler */ o = STRING(opts); @@ -1046,7 +1062,7 @@ BEGIN_METHOD_VOID(Window_Cls) /* ncurses sets the cursor to 0,0 after wclear() which may or may not be surprising. */ - wclear(CONTENT); + wclear(THIS->content); REFRESH(); END_METHOD @@ -1098,7 +1114,7 @@ BEGIN_METHOD(Window_DrawHLine, GB_INTEGER x; GB_INTEGER y; GB_INTEGER len; GB_ST int length, t; int i; - getyx(CONTENT, oy, ox); + getyx(THIS->content, oy, ox); c = *(STRING(ch)); length = VARG(len); if (MISSING(thickness)) @@ -1111,7 +1127,7 @@ BEGIN_METHOD(Window_DrawHLine, GB_INTEGER x; GB_INTEGER y; GB_INTEGER len; GB_ST for (i = 0; i < t; i++) { WINDOW_cursor_move(THIS, gx, gy); - whline(CONTENT, c, length); + whline(THIS->content, c, length); gy++; } WINDOW_cursor_move(THIS, ox, oy); @@ -1161,19 +1177,19 @@ BEGIN_METHOD(Window_PrintCenter, GB_STRING text) } p = STRING(text); - y = (getmaxy(CONTENT) - lines) / 2; + y = (getmaxy(THIS->content) - lines) / 2; while (lines--) { if (!lines) { - x = (getmaxx(CONTENT) - strlen(p)) / 2; + x = (getmaxx(THIS->content) - strlen(p)) / 2; WINDOW_print(THIS, p, x, y); } else { q = strchr(p, '\n'); *q = 0; - x = (getmaxx(CONTENT) - (q - p)) / 2; + x = (getmaxx(THIS->content) - (q - p)) / 2; WINDOW_print(THIS, p, x, y); y++; p = q + 1; @@ -1224,7 +1240,7 @@ BEGIN_METHOD(Window_DrawVLine, GB_INTEGER x; GB_INTEGER y; GB_INTEGER len; GB_ST int length, t; int i; - getyx(CONTENT, oy, ox); + getyx(THIS->content, oy, ox); c = *(STRING(ch)); length = VARG(len); if (MISSING(thickness)) @@ -1237,7 +1253,7 @@ BEGIN_METHOD(Window_DrawVLine, GB_INTEGER x; GB_INTEGER y; GB_INTEGER len; GB_ST for (i = 0; i < t; i++) { WINDOW_cursor_move(THIS, gx, gy); - wvline(CONTENT, c, length); + wvline(THIS->content, c, length); gx++; } WINDOW_cursor_move(THIS, ox, oy); @@ -1268,9 +1284,9 @@ BEGIN_PROPERTY(WindowAttrs_Normal) /* normal is special because it turns off all other attributes and can't itself been turned off */ if (READ_PROPERTY) - GB.ReturnBoolean(getattrs(CONTENT) == A_NORMAL); + GB.ReturnBoolean(getattrs(THIS->content) == A_NORMAL); if (VPROP(GB_BOOLEAN)) - wattrset(CONTENT, A_NORMAL); + wattrset(THIS->content, A_NORMAL); END_PROPERTY @@ -1300,8 +1316,20 @@ END_PROPERTY BEGIN_PROPERTY(WindowAttrs_Color) - //inch() attributes have the pair number, but we give the color pair to attron()? - //WIN_COLOR_METHOD(); + short pair; + + if (READ_PROPERTY) + { + GB.ReturnInteger(PAIR_NUMBER(getattrs(THIS->content))); + return; + } + pair = VPROP(GB_INTEGER); + if (!PAIR_VALID(pair)) + { + GB.Error(GB_ERR_BOUND); + return; + } + WINDOW_attrs_driver(THIS, COLOR_PAIR(pair), ATTR_DRV_COL); END_PROPERTY @@ -1311,6 +1339,14 @@ END_PROPERTY BEGIN_PROPERTY(CharAttrs_Normal) + if (READ_PROPERTY) + { + GB.ReturnBoolean(!WINDOW_char_attrs_driver(THIS, A_NORMAL, + THIS->pos.col, THIS->pos.line, ATTR_DRV_RET)); + return; + } + WINDOW_char_attrs_driver(THIS, A_NORMAL, THIS->pos.col, THIS->pos.line, ATTR_DRV_ON); + END_PROPERTY BEGIN_PROPERTY(CharAttrs_Underline) @@ -1343,13 +1379,33 @@ END_PROPERTY BEGIN_PROPERTY(CharAttrs_Color) + short pair; + + if (READ_PROPERTY) + { + pair = PAIR_NUMBER(WINDOW_char_attrs_driver(THIS, 0, + THIS->pos.col, THIS->pos.line, ATTR_DRV_RET)); + GB.ReturnInteger(pair); + return; + } + pair = VPROP(GB_INTEGER); + if (!PAIR_VALID(pair)) + { + GB.Error(GB_ERR_BOUND); + return; + } + WINDOW_char_attrs_driver(THIS, COLOR_PAIR(pair), THIS->pos.col, THIS->pos.line, ATTR_DRV_COL); + wtouchln(THIS->main, THIS->pos.line + (HAS_BORDER ? 1 : 0), 1, 1); + REFRESH(); + END_PROPERTY #define TIMEOUT_NOTIMEOUT -1 GB_DESC CWindowDesc[] = { - GB_DECLARE("Window", sizeof(CWINDOW)), + GB_DECLARE("Window", sizeof(struct nc_window)), + GB_AUTO_CREATABLE(), GB_EVENT("Read", NULL, NULL, &EVENT_Read), @@ -1366,10 +1422,10 @@ GB_DESC CWindowDesc[] = GB_PROPERTY("Buffered", "b", Window_Buffered), - GB_PROPERTY_READ("ClientHeight", "i", Window_ClientHeight), - GB_PROPERTY_READ("ClientH", "i", Window_ClientHeight), - GB_PROPERTY_READ("ClientWidth", "i", Window_ClientWidth), - GB_PROPERTY_READ("ClientW", "i", Window_ClientWidth), + GB_PROPERTY_READ("ContainerHeight", "i", Window_ContainerHeight), + GB_PROPERTY_READ("ContainerH", "i", Window_ContainerHeight), + GB_PROPERTY_READ("ContainerWidth", "i", Window_ContainerWidth), + GB_PROPERTY_READ("ComtainerW", "i", Window_ContainerWidth), GB_PROPERTY("CursorX", "i", Window_CursorX), GB_PROPERTY("CursorY", "i", Window_CursorY), @@ -1389,7 +1445,7 @@ GB_DESC CWindowDesc[] = GB_PROPERTY("Y", "i", Window_Y), /* Methods */ - GB_METHOD("_new", NULL, Window_new, "(X)i(Y)i(W)i(H)i"), + GB_METHOD("_new", NULL, Window_new, "[(X)i(Y)i(W)i(H)i]"), GB_METHOD("_free", NULL, Window_free, NULL), GB_METHOD("_get", ".Char.Attrs", Window_get, "(Y)i(X)i"), @@ -1440,6 +1496,8 @@ GB_DESC CWindowAttrsDesc[] = GB_PROPERTY("Blink", "b", WindowAttrs_Blink), GB_PROPERTY("Bold", "b", WindowAttrs_Bold), + GB_PROPERTY("Color", "i", WindowAttrs_Color), + GB_END_DECLARE }; @@ -1454,80 +1512,7 @@ GB_DESC CCharAttrsDesc[] = GB_PROPERTY("Blink", "b", CharAttrs_Blink), GB_PROPERTY("Bold", "b", CharAttrs_Bold), - //GB_PROPERTY("Color", "i", CCharAttrs_color), + GB_PROPERTY("Color", "i", CharAttrs_Color), GB_END_DECLARE }; - -GB_DESC CScreenDesc[] = -{ - GB_DECLARE("Screen", 0), GB_VIRTUAL_CLASS(), - - GB_EVENT("Read", NULL, NULL, &EVENT_Read), - - /* Constants */ - //GB_CONSTANT("NoTimeout", "i", TIMEOUT_NOTIMEOUT), - - /* Properties */ - //GB_PROPERTY_READ("Attributes", ".Window.Attrs", Window_Attrs), - - GB_STATIC_PROPERTY("Background", "i", Window_Background), - GB_STATIC_PROPERTY("Paper", "i", Window_Background), - - //GB_STATIC_PROPERTY("Border", "b", Window_Border), - - //GB_STATIC_PROPERTY("Buffered", "b", Window_Buffered), - - GB_STATIC_PROPERTY_READ("ClientHeight", "i", Window_ClientHeight), - GB_STATIC_PROPERTY_READ("ClientH", "i", Window_ClientHeight), - GB_STATIC_PROPERTY_READ("ClientWidth", "i", Window_ClientWidth), - GB_STATIC_PROPERTY_READ("ClientW", "i", Window_ClientWidth), - - GB_STATIC_PROPERTY("CursorX", "i", Window_CursorX), - GB_STATIC_PROPERTY("CursorY", "i", Window_CursorY), - - GB_STATIC_PROPERTY("Foreground", "i", Window_Foreground), - GB_STATIC_PROPERTY("Pen", "i", Window_Foreground), - - GB_STATIC_PROPERTY("Height", "i", Window_Height), - GB_STATIC_PROPERTY("H", "i", Window_Height), - - //GB_STATIC_PROPERTY("Wrap", "b", Window_Wrap), - - GB_STATIC_PROPERTY("Width", "i", Window_Width), - GB_STATIC_PROPERTY("W", "i", Window_Width), - - GB_STATIC_PROPERTY("X", "i", Window_X), - GB_STATIC_PROPERTY("Y", "i", Window_Y), - - /* Methods */ - //GB_STATIC_METHOD("_get", ".Char.Attrs", Window_get, "(Y)i(X)i"), - - GB_STATIC_METHOD("Ask", "s", Window_Ask, "(Opts)s[(Tries)i]"), - - GB_STATIC_METHOD("Bottom", NULL, Window_Bottom, NULL), - GB_STATIC_METHOD("Top", NULL, Window_Top, NULL), - - GB_STATIC_METHOD("Cls", NULL, Window_Cls, NULL), - - GB_STATIC_METHOD("Flush", NULL, Window_Flush, NULL), - - GB_STATIC_METHOD("Get", "s", Window_Get, "(X)i(Y)i[(Len)i]"), - - GB_STATIC_METHOD("DrawHLine", NULL, Window_DrawHLine, "(X)i(Y)i(Len)i(Ch)s[(Thickness)i]"), - GB_STATIC_METHOD("DrawVLine", NULL, Window_DrawVLine, "(X)i(Y)i(Len)i(Ch)s[(Thickness)i]"), - - GB_STATIC_METHOD("Insert", NULL, Window_Insert, "(Text)s[(X)i(Y)i]"), - GB_STATIC_METHOD("Print", NULL, Window_Print, "(Text)s[(X)i(Y)i]"), - GB_STATIC_METHOD("PrintCenter", NULL, Window_PrintCenter, "(Text)s"), - - GB_STATIC_METHOD("Locate", NULL, Window_Locate, "(X)i(Y)i"), - - GB_STATIC_METHOD("Refresh", NULL, Window_Refresh, NULL), - - GB_STATIC_METHOD("SetFocus", NULL, Window_SetFocus, NULL), - - GB_STATIC_METHOD("WaitKey", "i", Window_WaitKey, "[(Timeout)i]"), - - GB_END_DECLARE -}; diff --git a/gb.ncurses/src/c_window.h b/gb.ncurses/src/c_window.h index 59af23f5a..af36a68e8 100644 --- a/gb.ncurses/src/c_window.h +++ b/gb.ncurses/src/c_window.h @@ -31,14 +31,14 @@ #include "c_ncurses.h" #define THIS ((CWINDOW *) _object) -#define HAS_BORDER (THIS && THIS->border) -#define IS_WRAPPED (THIS && THIS->wrap) -#define IS_BUFFERED (THIS && THIS->buffered) +#define HAS_BORDER (THIS->border) +#define IS_WRAPPED (THIS->wrap) +#define IS_BUFFERED (THIS->buffered) /* This will produce final output on terminal screen */ #define REAL_REFRESH() WINDOW_real_refresh() /* This macro is mostly called by Gambas implementation functions to request output on screen (read: to check if the output is buffered and if not produce output by means of - REAL_REFRESH(). To check buffering, this need to get an object parameter.) */ + REAL_REFRESH(). To check buffering, this needs to get an object parameter.) */ #define REFRESH() WINDOW_refresh(THIS) /* Translate linear (absolute) memory addresses and x,y coordinates into each other @@ -71,7 +71,9 @@ enum /* Enable given attributes */ ATTR_DRV_ON, /* Disable given attributes */ - ATTR_DRV_OFF + ATTR_DRV_OFF, + /* Set a color */ + ATTR_DRV_COL }; #define WIN_ATTR_METHOD(b, a) { \ @@ -84,7 +86,6 @@ enum (b) ? ATTR_DRV_ON : ATTR_DRV_OFF); \ } #define WIN_ATTR_METHOD_BOOL(a) WIN_ATTR_METHOD(VPROP(GB_BOOLEAN), a); -#define WIN_ATTR_METHOD_INT(a) WIN_ATTR_METHOD(1, a); /* Notice the wtouchln() line in the following macro. It seems that a chgat() from nc_window_char_attrs_driver() doesn't mark anything dirty (no output on screen from a REFRESH()). So to make the new attribute available immidiately, we touch the affected @@ -100,42 +101,35 @@ enum wtouchln(THIS->main, THIS->pos.line + (HAS_BORDER ? 1 : 0), 1, 1); \ } #define CHAR_ATTR_METHOD_BOOL(a) CHAR_ATTR_METHOD(VPROP(GB_BOOLEAN), a); -#define CHAR_ATTR_METHOD_INT(a) CHAR_ATTR_METHOD(1, a); -//TODO: [x] chgat on line and character basis -// [-] Stream -// [-] Timer -// [-] Color +//TODO: [-] Stream -typedef - struct nc_window +typedef struct nc_window +{ + GB_BASE ob; + GB_STREAM stream; /* Gambas stream structure to enable Print #Window, Expr and other stream-related + syntaxes */ + WINDOW *main; /* The main window. */ + WINDOW *content; /* This window is used for all content-related operations. Its purpose is turning + the ncurses window borders which are inner-window to outer-window ones thus + separating border from content. If there is no border, this is the same as @main + otherwise a subwindow of it. */ + PANEL *pan; /* Panel of the main window to provide overlapping windows */ + bool border; /* Whether there is a border */ + bool wrap; /* Whether text shall be truncated or wrapped on line ends */ + bool buffered; /* Whether the output via REFRESH() macro shall be buffered (only a call to + Window.Refresh() will then produce any output) */ + struct /* This structure is used to pass a line and a column number to virtual objects */ { - GB_BASE ob; - GB_STREAM stream; /* Gambas stream structure to enable Print #Window, Expr and other stream-related - syntaxes */ - WINDOW *main; /* The main window. */ - WINDOW *content; /* This window is used for all content-related operations. Its purpose is turning - the ncurses window borders which are inner-window to outer-window ones thus - separating border from content. If there is no border, this is the same as @main - otherwise a subwindow of it. */ - PANEL *pan; /* Panel of the main window to provide overlapping windows */ - bool border; /* Whether there is a border */ - bool wrap; /* Whether text shall be truncated or wrapped on line ends */ - bool buffered; /* Whether the output via REFRESH() macro shall be buffered (only a call to - Window.Refresh() will then produce any output) */ - struct /* This structure is used to pass a line and a column number to virtual objects */ - { - int line; - int col; - } pos; - } - CWINDOW; + int line; + int col; + } pos; +} CWINDOW; #ifndef __C_WINDOW_C extern GB_DESC CWindowDesc[]; extern GB_DESC CWindowAttrsDesc[]; extern GB_DESC CCharAttrsDesc[]; -extern GB_DESC CScreenDesc[]; #endif #define WINDOW_main_to_content() WINDOW_copy_window(THIS->main, THIS->content, 0, 0, \ @@ -146,5 +140,6 @@ extern GB_DESC CScreenDesc[]; getmaxy(THIS->content), 0, 0) void WINDOW_real_refresh(); - +void WINDOW_refresh(); + #endif /* __C_WINDOW_C */ diff --git a/gb.ncurses/src/main.c b/gb.ncurses/src/main.c index 4cbbd1e32..55ca6a294 100644 --- a/gb.ncurses/src/main.c +++ b/gb.ncurses/src/main.c @@ -24,6 +24,8 @@ #include "c_ncurses.h" #include "c_window.h" #include "c_key.h" +#include "c_color.h" +#include "c_screen.h" #include "main.h" GB_INTERFACE GB EXPORT; @@ -34,8 +36,12 @@ GB_DESC *GB_CLASSES[] EXPORT = CWindowDesc, CWindowAttrsDesc, CCharAttrsDesc, - CScreenDesc, CKeyDesc, + CColorDesc, + CColorCapabilitiesDesc, + CColorPairDesc, + CColorContentDesc, + CScreenDesc, NULL }; @@ -44,7 +50,7 @@ static void hook_error(int code, char *error, char *where) NCURSES_exit(); } -static void hook_init() +static void hook_main(int *argc, char **argv) { NCURSES_init(); } @@ -52,7 +58,7 @@ static void hook_init() int EXPORT GB_INIT() { GB.Hook(GB_HOOK_ERROR, (void *) hook_error); - GB.Hook(GB_HOOK_MAIN, (void *) hook_init); + GB.Hook(GB_HOOK_MAIN, (void *) hook_main); return 0; } @@ -61,4 +67,3 @@ void EXPORT GB_EXIT() { NCURSES_exit(); } -