[GB.NCURSES]

* NEW: Added Color static class
* NEW: Added color support to Window class
* NEW: Window class now auto-creates a full-screen window
* NEW: Added Screen class for future use
* NEW: Moved symbols from NCurses to Screen where they belong now
* NEW: Key class supports array accessors as other Key classes do
* OPT: Drawing ASCII border if no alternate charset is supported
* BUG: Window.Print handles multiple lines correctly now
* BUG: Fixed Border problems with full-screen windows
* BUG: Fixed exchanged x,y parameters in resize internal function
* BUG: Fixed cursor mislead in internal function to copy window contents



git-svn-id: svn://localhost/gambas/trunk@4643 867c0c6c-44f3-4631-809d-bfa615b0a4ec
This commit is contained in:
Tobias Boege 2012-04-20 20:40:56 +00:00
parent 2575107f89
commit 07e789c365
11 changed files with 756 additions and 389 deletions

View File

@ -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

260
gb.ncurses/src/c_color.c Normal file
View File

@ -0,0 +1,260 @@
/*
* c_color.c - gb.ncurses Color static class
*
* Copyright (C) 2012 Tobias Boege <tobias@gambas-buch.de>
*
* 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 <ncurses.h>
#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
};

18
gb.ncurses/src/c_color.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef __C_COLOR_H
#define __C_COLOR_H
#include <ncurses.h>
#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 */

View File

@ -21,12 +21,19 @@
#define __C_KEY_C
#include "../gambas.h"
#include <ncurses.h>
#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
};

View File

@ -27,40 +27,11 @@
#include <ncurses.h>
#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),

View File

@ -25,7 +25,6 @@
#include <ncurses.h>
#include "gambas.h"
#include "gb_common.h"
#define NCURSES_RUNNING NCURSES_running()

198
gb.ncurses/src/c_screen.c Normal file
View File

@ -0,0 +1,198 @@
/*
* c_screen.c - gb.ncurses Screen class
*
* Copyright (C) 2012 Tobias Boege <tobias@gambas-buch.de>
*
* 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 <stdio.h>
#include <signal.h>
#include <ncurses.h>
#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
};

33
gb.ncurses/src/c_screen.h Normal file
View File

@ -0,0 +1,33 @@
/*
* c_screen.h - gb.ncurses Screen class
*
* Copyright (C) 2012 Tobias Boege <tobias@gambas-buch.de>
*
* 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 */

View File

@ -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 <curses.h> */
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
};

View File

@ -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 */

View File

@ -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();
}