From f73ceed77886cb0ca64cddc8404dca87a3aff6fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Minisini?= Date: Sun, 10 Apr 2016 13:10:25 +0000 Subject: [PATCH] [INTERPRETER] * NEW: Stream.Term.Width and Stream.Term.Height are two new properties that return the size of the terminal associated with the stream, if any. * NEW: As soon as the terminal size is read on any stream with the previous properties, the SIGWINCH signal is watched, and the Application_Resize() public method of the startup class is called each time this signal is catched, meaning that the terminal has been resized. git-svn-id: svn://localhost/gambas/trunk@7735 867c0c6c-44f3-4631-809d-bfa615b0a4ec --- main/gbx/gbx_c_file.c | 85 +++++++++++++++++++++++++++++++++------ main/gbx/gbx_c_file.h | 13 +++--- main/gbx/gbx_class_info.c | 24 +++++------ main/gbx/gbx_class_init.c | 12 +++--- main/gbx/gbx_exec_loop.c | 2 + 5 files changed, 99 insertions(+), 37 deletions(-) diff --git a/main/gbx/gbx_c_file.c b/main/gbx/gbx_c_file.c index 85417c75a..260447c95 100644 --- a/main/gbx/gbx_c_file.c +++ b/main/gbx/gbx_c_file.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "gb_common.h" #include "gb_list.h" @@ -46,6 +47,7 @@ #include "gbx_string.h" #include "gbx_date.h" #include "gbx_watch.h" +#include "gbx_signal.h" #include "gbx_c_file.h" @@ -56,10 +58,18 @@ CFILE *CFILE_in, *CFILE_out, *CFILE_err; DECLARE_EVENT(EVENT_Read); DECLARE_EVENT(EVENT_Write); -static GB_FUNCTION read_func; +static GB_FUNCTION _read_func; static char _buffer[16]; +static bool _term_init = FALSE; +static bool _has_term_func = FALSE; +static ushort _term_width = 0; +static ushort _term_height = 0; +static SIGNAL_CALLBACK *_SIGWINCH_callback = NULL; +static GB_FUNCTION _term_resize_func; + + static void callback_read(int fd, int type, CFILE *file) { if (!STREAM_read_ahead(CSTREAM_stream(file))) @@ -68,12 +78,18 @@ static void callback_read(int fd, int type, CFILE *file) WATCH_little_sleep(); } - static void callback_write(int fd, int type, CFILE *file) { GB_Raise(file, EVENT_Write, 0); } +static void cb_term_resize(int signum, intptr_t data) +{ + _term_width = _term_height = 0; + if (_has_term_func) + GB_Call(&_term_resize_func, 0, FALSE); +} + CFILE *CFILE_create(STREAM *stream, int mode) { @@ -134,11 +150,14 @@ void CFILE_exit(void) OBJECT_UNREF(CFILE_in); OBJECT_UNREF(CFILE_out); OBJECT_UNREF(CFILE_err); + + if (_term_init) + SIGNAL_unregister(SIGWINCH, _SIGWINCH_callback); } void CFILE_init_watch(void) { - if (GB_GetFunction(&read_func, PROJECT_class, "Application_Read", "", "") == 0) + if (GB_GetFunction(&_read_func, PROJECT_class, "Application_Read", "", "") == 0) { //fprintf(stderr, "watch stdin\n"); OBJECT_attach((OBJECT *)CFILE_in, (OBJECT *)PROJECT_class, "Application"); @@ -852,6 +871,8 @@ BEGIN_METHOD_VOID(StreamLines_next) END_METHOD +//--------------------------------------------------------------------------- + BEGIN_PROPERTY(StreamTerm_Name) GB_ReturnNewZeroString(ttyname(STREAM_FD)); @@ -913,30 +934,69 @@ BEGIN_PROPERTY(StreamTerm_FlowControl) END_PROPERTY +static void init_term_size(void *_object) +{ + struct winsize winSize; + + if (_term_width == 0 || _term_height == 0) + { + if (ioctl(STREAM_FD, TIOCGWINSZ, (char *)&winSize)) + THROW_SYSTEM(errno, NULL); + + _term_width = winSize.ws_col; + _term_height = winSize.ws_row; + } + + if (!_term_init) + { + _SIGWINCH_callback = SIGNAL_register(SIGWINCH, cb_term_resize, 0); + _has_term_func = GB_GetFunction(&_term_resize_func, PROJECT_class, "Application_Resize", "", "") == 0; + _term_init = TRUE; + } +} + +BEGIN_PROPERTY(StreamTerm_Width) + + init_term_size(_object); + GB_ReturnInteger(_term_width); + +END_PROPERTY + +BEGIN_PROPERTY(StreamTerm_Height) + + init_term_size(_object); + GB_ReturnInteger(_term_height); + +END_PROPERTY + #endif -GB_DESC NATIVE_StreamLines[] = +GB_DESC StreamLinesDesc[] = { - GB_DECLARE(".Stream.Lines", 0), GB_VIRTUAL_CLASS(), + GB_DECLARE_VIRTUAL(".Stream.Lines"), GB_METHOD("_next", "s", StreamLines_next, NULL), GB_END_DECLARE }; -GB_DESC NATIVE_StreamTerm[] = +GB_DESC StreamTermDesc[] = { - GB_DECLARE(".Stream.Term", 0), GB_VIRTUAL_CLASS(), + GB_DECLARE_VIRTUAL(".Stream.Term"), GB_PROPERTY_READ("Name", "s", StreamTerm_Name), GB_PROPERTY("Echo", "b", StreamTerm_Echo), GB_PROPERTY("FlowControl", "b", StreamTerm_FlowControl), + GB_PROPERTY_READ("Width", "i", StreamTerm_Width), + GB_PROPERTY_READ("W", "i", StreamTerm_Width), + GB_PROPERTY_READ("Height", "i", StreamTerm_Height), + GB_PROPERTY_READ("H", "i", StreamTerm_Height), GB_METHOD("Resize", NULL, StreamTerm_Resize, "(Width)i(Height)i"), GB_END_DECLARE }; -GB_DESC NATIVE_Stream[] = +GB_DESC StreamDesc[] = { GB_DECLARE("Stream", sizeof(CSTREAM)), GB_NOT_CREATABLE(), @@ -964,10 +1024,9 @@ GB_DESC NATIVE_Stream[] = }; -GB_DESC NATIVE_StatPerm[] = +GB_DESC StatPermDesc[] = { - GB_DECLARE(".Stat.Perm", 0), - GB_VIRTUAL_CLASS(), + GB_DECLARE_VIRTUAL(".Stat.Perm"), GB_METHOD("_get", "s", CFILE_perm_get, "(UserOrGroup)s"), GB_PROPERTY_READ("User", "s", CFILE_perm_user), @@ -978,7 +1037,7 @@ GB_DESC NATIVE_StatPerm[] = }; -GB_DESC NATIVE_Stat[] = +GB_DESC StatDesc[] = { GB_DECLARE("Stat", sizeof(CSTAT)), GB_NOT_CREATABLE(), @@ -1007,7 +1066,7 @@ GB_DESC NATIVE_Stat[] = }; -GB_DESC NATIVE_File[] = +GB_DESC FileDesc[] = { GB_DECLARE("File", sizeof(CFILE)), GB_INHERITS("Stream"), diff --git a/main/gbx/gbx_c_file.h b/main/gbx/gbx_c_file.h index 32abde5bf..36ed64594 100644 --- a/main/gbx/gbx_c_file.h +++ b/main/gbx/gbx_c_file.h @@ -55,12 +55,13 @@ typedef CSTAT; #ifndef __GBX_C_FILE_C -extern GB_DESC NATIVE_StreamLines[]; -extern GB_DESC NATIVE_StreamTerm[]; -extern GB_DESC NATIVE_Stream[]; -extern GB_DESC NATIVE_File[]; -extern GB_DESC NATIVE_Stat[]; -extern GB_DESC NATIVE_StatPerm[]; +extern GB_DESC StreamLinesDesc[]; +extern GB_DESC StreamTermDesc[]; +extern GB_DESC StreamDesc[]; +extern GB_DESC FileDesc[]; +extern GB_DESC StatDesc[]; +extern GB_DESC StatPermDesc[]; + extern CFILE *CFILE_in; extern CFILE *CFILE_out; extern CFILE *CFILE_err; diff --git a/main/gbx/gbx_class_info.c b/main/gbx/gbx_class_info.c index 770b144b9..5e4f0472d 100644 --- a/main/gbx/gbx_class_info.c +++ b/main/gbx/gbx_class_info.c @@ -358,12 +358,12 @@ extern GB_DESC NATIVE_Components[]; extern GB_DESC NATIVE_Object[]; extern GB_DESC NATIVE_Collection[]; extern GB_DESC NATIVE_Error[]; -extern GB_DESC NATIVE_Stream[]; -extern GB_DESC NATIVE_StreamLines[]; -extern GB_DESC NATIVE_StreamTerm[]; -extern GB_DESC NATIVE_StatPerm[]; -extern GB_DESC NATIVE_Stat[]; -extern GB_DESC NATIVE_File[]; +extern GB_DESC StreamDesc[]; +extern GB_DESC StreamLinesDesc[]; +extern GB_DESC StreamTermDesc[]; +extern GB_DESC StatPermDesc[]; +extern GB_DESC StatDesc[]; +extern GB_DESC FileDesc[]; extern GB_DESC NATIVE_AppEnv[]; extern GB_DESC NATIVE_AppArgs[]; extern GB_DESC NATIVE_App[]; @@ -406,12 +406,12 @@ GB_DESC *GB_CLASSES[] EXPORT = NATIVE_Object, NATIVE_Collection, NATIVE_Error, - NATIVE_StreamLines, - NATIVE_StreamTerm, - NATIVE_Stream, - NATIVE_StatPerm, - NATIVE_Stat, - NATIVE_File, + StreamLinesDesc, + StreamTermDesc, + StreamDesc, + StatPermDesc, + StatDesc, + FileDesc, NATIVE_AppEnv, NATIVE_AppArgs, NATIVE_App, diff --git a/main/gbx/gbx_class_init.c b/main/gbx/gbx_class_init.c index ae731b75b..41ef9beb4 100644 --- a/main/gbx/gbx_class_init.c +++ b/main/gbx/gbx_class_init.c @@ -100,12 +100,12 @@ static const CLASS_INIT init_list[] = { NATIVE_Object, NULL }, { NATIVE_Collection, &CLASS_Collection, CQA_COLLECTION }, { NATIVE_Error, NULL }, - { NATIVE_StreamLines, NULL }, - { NATIVE_StreamTerm, NULL }, - { NATIVE_Stream, &CLASS_Stream }, - { NATIVE_StatPerm, NULL }, - { NATIVE_Stat, &CLASS_Stat }, - { NATIVE_File, &CLASS_File }, + { StreamLinesDesc, NULL }, + { StreamTermDesc, NULL }, + { StreamDesc, &CLASS_Stream }, + { StatPermDesc, NULL }, + { StatDesc, &CLASS_Stat }, + { FileDesc, &CLASS_File }, { NATIVE_AppEnv, &CLASS_AppEnv }, { NATIVE_AppArgs, &CLASS_AppArgs }, { NATIVE_App, &CLASS_Application }, diff --git a/main/gbx/gbx_exec_loop.c b/main/gbx/gbx_exec_loop.c index c2588a885..b2b9c9d65 100644 --- a/main/gbx/gbx_exec_loop.c +++ b/main/gbx/gbx_exec_loop.c @@ -3751,6 +3751,8 @@ static void _break(ushort code) TC = PC + 1; TP = SP; + //fprintf(stderr, "%s\n", DEBUG_get_current_position()); + if (CP && CP->component == COMPONENT_main) { if (EXEC_profile_instr)