implemented MooTermVt for unix

This commit is contained in:
Yevgen Muntyan 2005-06-22 22:13:12 +00:00
parent 9985fd84fd
commit 1ca2e621d1
10 changed files with 838 additions and 104 deletions

View File

@ -20,6 +20,14 @@ widget_sources = \
mootermvt.c \ mootermvt.c \
mootermvt.h mootermvt.h
widget_unix_sources = \
mootermvt-unix.c \
pty.c \
pty.h
widget_win32_sources = \
mootermvt-win32.c
AM_INCLUDES = AM_INCLUDES =
common_cflags = \ common_cflags = \
-I$(top_builddir) \ -I$(top_builddir) \
@ -29,9 +37,55 @@ common_cflags = \
$(PYGTK_CFLAGS) \ $(PYGTK_CFLAGS) \
$(GTK_CFLAGS) \ $(GTK_CFLAGS) \
-DG_LOG_DOMAIN=\"Moo\" -DG_LOG_DOMAIN=\"Moo\"
AM_CFLAGS = $(common_cflags) $(M_CFLAGS) $(CFLAGS) AM_CFLAGS = $(common_cflags) $(M_CFLAGS) $(CFLAGS)
AM_CXXFLAGS = $(common_cflags) $(M_CXXFLAGS) $(CXXFLAGS) AM_CXXFLAGS = $(common_cflags) $(M_CXXFLAGS) $(CXXFLAGS)
EXTRA_DIST = \
$(widget_sources) \
$(widget_unix_sources) \
$(widget_win32_sources)
############################################################################
# UNIX
#
if UNIX_BUILD
noinst_LTLIBRARIES = libmooterm.la noinst_LTLIBRARIES = libmooterm.la
libmooterm_la_SOURCES = $(widget_sources) libmooterm_la_SOURCES = $(widget_sources) $(widget_unix_sources)
endif UNIX_BUILD
############################################################################
# MINGW
#
if MINGW_BUILD
noinst_LTLIBRARIES = libmooterm.la
libmooterm_la_SOURCES = $(widget_sources) $(widget_win32_sources)
endif MINGW_BUILD
############################################################################
# CYGWIN
#
if CYGWIN_BUILD
noinst_PROGRAMS = termhelper
termhelper_CFLAGS = \
$(AM_CFLAGS) \
$(CYGWIN_CFLAGS)
termhelper_SOURCES = $(termhelper_sources)
termhelper_LDADD = $(CYGWIN_LDFLAGS) termhelper_res.res
termhelper_res.res: termhelper_res.rc
$(WINDRES) -i termhelper_res.rc --input-format=rc -o termhelper_res.res -O coff
endif CYGWIN_BUILD

View File

@ -649,3 +649,15 @@ void moo_term_size_changed (MooTerm *term)
moo_term_buffer_set_screen_size (term->priv->buffer, width, height); moo_term_buffer_set_screen_size (term->priv->buffer, width, height);
moo_term_vt_set_size (term->priv->vt, width, height); moo_term_vt_set_size (term->priv->vt, width, height);
} }
gboolean moo_term_fork_command (MooTerm *term,
const char *cmd,
const char *working_dir,
char **envp)
{
g_return_val_if_fail (MOO_IS_TERM (term), FALSE);
return moo_term_vt_fork_command (term->priv->vt,
cmd, working_dir, envp);
}

View File

@ -56,6 +56,11 @@ MooTermBuffer *moo_term_get_buffer (MooTerm *term);
void moo_term_set_adjustment (MooTerm *term, void moo_term_set_adjustment (MooTerm *term,
GtkAdjustment *vadj); GtkAdjustment *vadj);
gboolean moo_term_fork_command (MooTerm *term,
const char *cmd,
const char *working_dir,
char **envp);
G_END_DECLS G_END_DECLS

View File

@ -0,0 +1,499 @@
/*
* mooterm/mootermvt-unix.c
*
* Copyright (C) 2004-2005 by Yevgen Muntyan <muntyan@math.tamu.edu>
*
* 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 of the License, or
* (at your option) any later version.
*
* See COPYING file that comes with this distribution.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "mooterm/mootermvt.h"
#include "mooterm/pty.h"
#include "mooutils/moomarshals.h"
#include "mooutils/moocompat.h"
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#ifdef HAVE_POLL_H
#include <poll.h>
#elif HAVE_SYS_POLL_H
#include <sys/poll.h>
#endif
#define TERM_EMULATION "xterm"
#define READ_BUFSIZE 4096
#define POLL_TIME 5
#define POLL_NUM 1
#define MOO_TERM_VT_UNIX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MOO_TYPE_TERM_VT_UNIX, MooTermVtUnix))
#define MOO_TERM_VT_UNIX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOO_TYPE_TERM_VT_UNIX, MooTermVtUnixClass))
#define MOO_IS_TERM_VT_UNIX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MOO_TYPE_TERM_VT_UNIX))
#define MOO_IS_TERM_VT_UNIX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MOO_TYPE_TERM_VT_UNIX))
#define MOO_TERM_VT_UNIX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MOO_TYPE_TERM_VT_UNIX, MooTermVtUnixClass))
typedef struct _MooTermVtUnix MooTermVtUnix;
typedef struct _MooTermVtUnixClass MooTermVtUnixClass;
struct _MooTermVtUnix {
MooTermVt parent;
gboolean child_alive;
GPid child_pid;
int master;
int width;
int height;
GIOChannel *io;
guint io_watch_id;
};
struct _MooTermVtUnixClass {
MooTermVtClass parent_class;
};
static void moo_term_vt_unix_finalize (GObject *object);
static void set_size (MooTermVt *vt,
gulong width,
gulong height);
static gboolean fork_command (MooTermVt *vt,
const char *cmd,
const char *working_dir,
char **envp);
static void feed_child (MooTermVt *vt,
const char *string,
gssize len);
static void kill_child (MooTermVt *vt);
static gboolean read_child_out (GIOChannel *source,
GIOCondition condition,
MooTermVtUnix *vt);
static void feed_parent (MooTermVtUnix *vt,
const char *string,
gssize len);
/* MOO_TYPE_TERM_VT_UNIX */
G_DEFINE_TYPE (MooTermVtUnix, moo_term_vt_unix, MOO_TYPE_TERM_VT)
static void moo_term_vt_unix_class_init (MooTermVtUnixClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
MooTermVtClass *vt_class = MOO_TERM_VT_CLASS (klass);
gobject_class->finalize = moo_term_vt_unix_finalize;
vt_class->set_size = set_size;
vt_class->fork_command = fork_command;
vt_class->feed_child = feed_child;
vt_class->kill_child = kill_child;
}
static void moo_term_vt_unix_init (MooTermVtUnix *vt)
{
vt->child_alive = FALSE;
vt->child_pid = (GPid)-1;
vt->master = -1;
vt->width = 80;
vt->height = 24;
vt->io = NULL;
vt->io_watch_id = 0;
}
static void moo_term_vt_unix_finalize (GObject *object)
{
MooTermVtUnix *vt = MOO_TERM_VT_UNIX (object);
kill_child (MOO_TERM_VT (vt));
G_OBJECT_CLASS (moo_term_vt_unix_parent_class)->finalize (object);
}
static void set_size (MooTermVt *vt,
gulong width,
gulong height)
{
MooTermVtUnix *vtu;
g_return_if_fail (MOO_IS_TERM_VT_UNIX (vt));
vtu = MOO_TERM_VT_UNIX (vt);
if (vtu->child_alive)
_vte_pty_set_size (vtu->master, width, height);
vtu->width = width;
vtu->height = height;
}
static gboolean fork_command (MooTermVt *vt_gen,
const char *cmd,
const char *working_dir,
char **envp)
{
MooTermVtUnix *vt;
int argv_len;
char **argv = NULL;
int env_len = 0;
char **new_env;
GError *err = NULL;
int status, flags;
int i;
g_return_val_if_fail (cmd != NULL, FALSE);
g_return_val_if_fail (MOO_IS_TERM_VT_UNIX (vt_gen), FALSE);
vt = MOO_TERM_VT_UNIX (vt_gen);
g_return_val_if_fail (!vt->child_alive, FALSE);
if (!g_shell_parse_argv (cmd, &argv_len, &argv, &err))
{
g_critical ("%s: could not parse command line", G_STRLOC);
if (err != NULL)
{
g_critical ("%s: %s", G_STRLOC, err->message);
g_error_free (err);
}
if (argv != NULL)
g_strfreev (argv);
return FALSE;
}
if (envp)
{
char **e;
for (e = envp; *e != NULL; ++e)
++env_len;
}
new_env = g_new (char*, env_len + 2);
for (i = 0; i < env_len; ++i)
new_env[i] = g_strdup (envp[i]);
new_env[env_len] = g_strdup ("TERM=" TERM_EMULATION);
new_env[env_len + 1] = NULL;
vt->master = _vte_pty_open (&vt->child_pid, new_env,
argv[0],
argv,
working_dir,
vt->width, vt->height,
FALSE, FALSE, FALSE);
g_strfreev (new_env);
if (vt->master == -1)
{
g_critical ("%s: could not fork child", G_STRLOC);
return FALSE;
}
else
{
g_message ("%s: forked child pid %d", G_STRLOC, vt->child_pid);
}
if (waitpid (-1, &status, WNOHANG) == -1)
g_critical ("%s: error in waitpid", G_STRLOC);
if ((flags = fcntl (vt->master, F_GETFL)) < 0)
g_critical ("%s: F_GETFL on master", G_STRLOC);
else if (-1 == fcntl (vt->master, F_SETFL, O_NONBLOCK | flags))
g_critical ("%s: F_SETFL on master", G_STRLOC);
vt->io = g_io_channel_unix_new (vt->master);
g_return_val_if_fail (vt->io != NULL, FALSE);
g_io_channel_set_encoding (vt->io, NULL, NULL);
g_io_channel_set_buffered (vt->io, FALSE);
vt->io_watch_id = g_io_add_watch (vt->io,
G_IO_IN | G_IO_PRI | G_IO_HUP,
(GIOFunc) read_child_out,
vt);
#if 0
// GSource *src = g_main_context_find_source_by_id (NULL, helper_out_watch_id);
// if (src) g_source_set_priority (src, READ_HELPER_OUT_PRIORITY);
// else g_warning ("%s: could not find helper_io_watch source", G_STRLOC);
#endif
vt->child_alive = TRUE;
return TRUE;
}
static void kill_child (MooTermVt *vt_gen)
{
MooTermVtUnix *vt = MOO_TERM_VT_UNIX (vt_gen);
if (vt->io_watch_id)
{
g_source_remove (vt->io_watch_id);
vt->io_watch_id = 0;
}
if (vt->io)
{
feed_child (MOO_TERM_VT (vt), "\4", 1);
g_io_channel_shutdown (vt->io, TRUE, NULL);
g_io_channel_unref (vt->io);
vt->io = NULL;
}
if (vt->master != -1)
{
_vte_pty_close (vt->master);
vt->master = -1;
}
vt->child_pid = (GPid)-1;
if (vt->child_alive)
{
vt->child_alive = FALSE;
g_signal_emit_by_name (vt, "child-died");
}
}
static gboolean read_child_out (G_GNUC_UNUSED GIOChannel *source,
GIOCondition condition,
MooTermVtUnix *vt)
{
gboolean error_occured = FALSE;
int error_no = 0;
char buf[READ_BUFSIZE];
int current = 0;
guint again = POLL_NUM;
if (condition & G_IO_HUP)
{
g_message ("%s: G_IO_HUP", G_STRLOC);
error_no = errno;
goto error;
}
else if (condition & G_IO_ERR)
{
g_message ("%s: G_IO_ERR", G_STRLOC);
error_no = errno;
goto error;
}
g_assert (condition & (G_IO_IN | G_IO_PRI));
while (again && !error_occured && current < READ_BUFSIZE)
{
struct pollfd fd = {vt->master, POLLIN | POLLPRI, 0};
int res = poll (&fd, 1, POLL_TIME);
switch (res)
{
case 0:
--again;
break;
case 1:
if (fd.revents & (POLLNVAL | POLLERR | POLLHUP))
{
again = 0;
if (errno != EAGAIN && errno != EINTR)
{
error_occured = TRUE;
error_no = errno;
}
}
else if (fd.revents & (POLLIN | POLLPRI))
{
int r = read (vt->master, buf + current, 1);
switch (r)
{
case -1:
error_occured = TRUE;
error_no = errno;
break;
case 0:
--again;
break;
case 1:
++current;
break;
default:
g_assert_not_reached();
}
}
break;
case -1:
again = 0;
if (errno != EAGAIN && errno != EINTR)
{
error_occured = TRUE;
error_no = errno;
}
break;
default:
g_assert_not_reached();
}
}
if (current > 0)
feed_parent (vt, buf, current);
if (error_occured)
goto error;
return TRUE;
error:
if (error_occured)
g_message ("error in %s", G_STRLOC);
if (error_no)
g_message ("%s: %s", G_STRLOC, g_strerror (error_no));
if (vt->io)
{
_vte_pty_close (vt->master);
vt->master = -1;
g_io_channel_shutdown (vt->io, TRUE, NULL);
g_io_channel_unref (vt->io);
vt->io = NULL;
vt->io_watch_id = 0;
}
kill_child (MOO_TERM_VT (vt));
return FALSE;
}
static void feed_parent (MooTermVtUnix *vt,
const char *string,
gssize len)
{
moo_term_buffer_feed (moo_term_vt_get_buffer (MOO_TERM_VT (vt)),
string, len);
}
#define CHUNK_SIZE 1024
static void feed_child (MooTermVt *vt_gen,
const char *string,
gssize len)
{
guint total_written = 0;
GError *err = NULL;
guint eagain_count = 0;
MooTermVtUnix *vt = MOO_TERM_VT_UNIX (vt_gen);
g_return_if_fail (vt->io != NULL);
if (len < 0)
len = strlen (string);
while (total_written < (guint)len)
{
gsize written = 0;
GIOStatus status;
status = g_io_channel_write_chars (vt->io, string + total_written,
MIN (len - total_written, CHUNK_SIZE),
&written, &err);
if (err)
{
g_critical ("%s: %s", G_STRLOC, err->message);
g_error_free (err);
break;
}
if (status != G_IO_STATUS_NORMAL)
{
gboolean stop = FALSE;
switch (status)
{
case G_IO_STATUS_ERROR:
g_critical ("%s: g_io_channel_write_chars returned G_IO_STATUS_ERROR", G_STRLOC);
stop = TRUE;
break;
case G_IO_STATUS_EOF:
g_critical ("%s: g_io_channel_write_chars returned G_IO_STATUS_EOF", G_STRLOC);
stop = TRUE;
break;
case G_IO_STATUS_AGAIN:
++eagain_count;
if (eagain_count > 2)
{
g_critical ("%s: g_io_channel_write_chars returned G_IO_STATUS_AGAIN 2 times", G_STRLOC);
stop = TRUE;
}
else
{
g_usleep (10000);
}
break;
default:
g_assert_not_reached ();
}
if (stop)
break;
}
else if (written <= 0)
{
g_critical ("%s: error in g_io_channel_write_chars", G_STRLOC);
break;
}
total_written += written;
}
}

View File

@ -0,0 +1,16 @@
/*
* mooterm/mootermvt-win32.c
*
* Copyright (C) 2004-2005 by Yevgen Muntyan <muntyan@math.tamu.edu>
*
* 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 of the License, or
* (at your option) any later version.
*
* See COPYING file that comes with this distribution.
*/
#include "mooterm/mootermvt.h"

View File

@ -12,6 +12,8 @@
*/ */
#include "mooterm/mootermvt.h" #include "mooterm/mootermvt.h"
#include "mooutils/moomarshals.h"
#include "mooutils/moocompat.h"
struct _MooTermVtPrivate { struct _MooTermVtPrivate {
@ -34,6 +36,7 @@ static void moo_term_vt_finalize (GObject *object);
G_DEFINE_TYPE (MooTermVt, moo_term_vt, G_TYPE_OBJECT) G_DEFINE_TYPE (MooTermVt, moo_term_vt, G_TYPE_OBJECT)
enum { enum {
CHILD_DIED,
LAST_SIGNAL LAST_SIGNAL
}; };
@ -42,7 +45,7 @@ enum {
PROP_BUFFER PROP_BUFFER
}; };
// static guint signals[LAST_SIGNAL]; static guint signals[LAST_SIGNAL];
static void moo_term_vt_class_init (MooTermVtClass *klass) static void moo_term_vt_class_init (MooTermVtClass *klass)
@ -53,6 +56,21 @@ static void moo_term_vt_class_init (MooTermVtClass *klass)
gobject_class->get_property = moo_term_vt_get_property; gobject_class->get_property = moo_term_vt_get_property;
gobject_class->finalize = moo_term_vt_finalize; gobject_class->finalize = moo_term_vt_finalize;
klass->set_size = NULL;
klass->fork_command = NULL;
klass->feed_child = NULL;
klass->kill_child = NULL;
klass->child_died = NULL;
signals[CHILD_DIED] =
g_signal_new ("child-died",
G_OBJECT_CLASS_TYPE (gobject_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (MooTermVtClass, child_died),
NULL, NULL,
_moo_marshal_VOID__VOID,
G_TYPE_NONE, 0);
g_object_class_install_property (gobject_class, g_object_class_install_property (gobject_class,
PROP_BUFFER, PROP_BUFFER,
g_param_spec_object ("buffer", g_param_spec_object ("buffer",
@ -143,13 +161,44 @@ MooTermBuffer *moo_term_vt_get_buffer (MooTermVt *vt)
MooTermVt *moo_term_vt_new (void) MooTermVt *moo_term_vt_new (void)
{ {
return MOO_TERM_VT (g_object_new (MOO_TYPE_TERM_VT, NULL)); #ifdef __WIN32__
return g_object_new (MOO_TYPE_TERM_VT_WIN, NULL);
#else /* !__WIN32__ */
return g_object_new (MOO_TYPE_TERM_VT_UNIX, NULL);
#endif /* !__WIN32__ */
} }
void moo_term_vt_set_size (G_GNUC_UNUSED MooTermVt *vt, void moo_term_vt_set_size (MooTermVt *vt,
G_GNUC_UNUSED gulong width, gulong width,
G_GNUC_UNUSED gulong height) gulong height)
{ {
// g_message ("%s: implement me", G_STRLOC); g_return_if_fail (MOO_IS_TERM_VT (vt));
MOO_TERM_VT_GET_CLASS(vt)->set_size (vt, width, height);
}
gboolean moo_term_vt_fork_command (MooTermVt *vt,
const char *cmd,
const char *working_dir,
char **envp)
{
g_return_val_if_fail (MOO_IS_TERM_VT (vt), FALSE);
return MOO_TERM_VT_GET_CLASS(vt)->fork_command (vt, cmd, working_dir, envp);
}
void moo_term_vt_kill_child (MooTermVt *vt)
{
g_return_if_fail (MOO_IS_TERM_VT (vt));
MOO_TERM_VT_GET_CLASS(vt)->kill_child (vt);
}
void moo_term_vt_feed_child (MooTermVt *vt,
const char *data,
gssize len)
{
g_return_if_fail (MOO_IS_TERM_VT (vt));
MOO_TERM_VT_GET_CLASS(vt)->feed_child (vt, data, len);
} }

View File

@ -20,6 +20,9 @@ G_BEGIN_DECLS
#define MOO_TYPE_TERM_VT (moo_term_vt_get_type ()) #define MOO_TYPE_TERM_VT (moo_term_vt_get_type ())
#define MOO_TYPE_TERM_VT_WIN (moo_term_vt_win_get_type ())
#define MOO_TYPE_TERM_VT_UNIX (moo_term_vt_unix_get_type ())
#define MOO_TERM_VT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MOO_TYPE_TERM_VT, MooTermVt)) #define MOO_TERM_VT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MOO_TYPE_TERM_VT, MooTermVt))
#define MOO_TERM_VT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOO_TYPE_TERM_VT, MooTermVtClass)) #define MOO_TERM_VT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOO_TYPE_TERM_VT, MooTermVtClass))
#define MOO_IS_TERM_VT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MOO_TYPE_TERM_VT)) #define MOO_IS_TERM_VT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MOO_TYPE_TERM_VT))
@ -38,19 +41,49 @@ struct _MooTermVt {
struct _MooTermVtClass { struct _MooTermVtClass {
GObjectClass parent_class; GObjectClass parent_class;
/* virtual methods */
void (*set_size) (MooTermVt *vt,
gulong width,
gulong height);
gboolean (*fork_command) (MooTermVt *vt,
const char *cmd,
const char *working_dir,
char **envp);
void (*feed_child) (MooTermVt *vt,
const char *data,
gssize len);
void (*kill_child) (MooTermVt *vt);
/* signals */
void (*child_died) (MooTermVt *vt);
}; };
GType moo_term_vt_get_type (void) G_GNUC_CONST; GType moo_term_vt_get_type (void) G_GNUC_CONST;
GType moo_term_vt_unix_get_type (void) G_GNUC_CONST;
GType moo_term_vt_win_get_type (void) G_GNUC_CONST;
MooTermVt *moo_term_vt_new (void); /* creates MooTermVtWin or MooTermVtUnix instance, depending on platform */
void moo_term_vt_set_size (MooTermVt *vt, MooTermVt *moo_term_vt_new (void);
gulong width,
gulong height);
void moo_term_vt_set_buffer (MooTermVt *vt, void moo_term_vt_set_buffer (MooTermVt *vt,
MooTermBuffer *buffer); MooTermBuffer *buffer);
MooTermBuffer *moo_term_vt_get_buffer (MooTermVt *vt); MooTermBuffer *moo_term_vt_get_buffer (MooTermVt *vt);
void moo_term_vt_set_size (MooTermVt *vt,
gulong width,
gulong height);
gboolean moo_term_vt_fork_command (MooTermVt *vt,
const char *cmd,
const char *working_dir,
char **envp);
void moo_term_vt_kill_child (MooTermVt *vt);
void moo_term_vt_feed_child (MooTermVt *vt,
const char *data,
gssize len);
G_END_DECLS G_END_DECLS

View File

@ -2,7 +2,7 @@
# tests/Makefile.am # tests/Makefile.am
# #
EXTRA_PROGRAMS = medit mterm markup editor EXTRA_PROGRAMS = medit mterm markup editor termbuffer
noinst_PROGRAMS = noinst_PROGRAMS =
EXTRA_DIST = pyapp.py.in EXTRA_DIST = pyapp.py.in
@ -15,7 +15,7 @@ if BUILD_MOOEDIT
noinst_PROGRAMS += medit noinst_PROGRAMS += medit
endif endif
if BUILD_MOOTERM if BUILD_MOOTERM
noinst_PROGRAMS += mterm noinst_PROGRAMS += mterm termbuffer
endif endif
if BUILD_MOOUTILS if BUILD_MOOUTILS
noinst_PROGRAMS += markup noinst_PROGRAMS += markup
@ -74,14 +74,17 @@ medit_SOURCES = medit.cpp
## ##
mterm_LDFLAGS = mterm_LDFLAGS =
mterm_LDADD = $(MOO_LIBS) ../moo/libmoo.la mterm_LDADD = $(MOO_LIBS) ../moo/libmoo.la
termbuffer_LDADD = $(mterm_LDADD)
if MINGW_BUILD if MINGW_BUILD
mterm_LDFLAGS += -mwindows mterm_LDFLAGS += -mwindows
endif MINGW_BUILD endif MINGW_BUILD
mterm_SOURCES = \ termbuffer_LDFLAGS = $(mterm_LDFLAGS)
mterm.cpp
mterm_SOURCES = mterm.cpp
termbuffer_SOURCES = termbuffer.cpp
############################################################################## ##############################################################################

View File

@ -17,89 +17,26 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#ifndef __WIN32__
#define CMD "sh"
#else
#define CMD "gapw95.exe"
#endif
#define CLEAR "\033[H\033[2J"
#define HOME "\033[H"
#define PARM_RIGHT "\033[%dC"
#define PARM_LEFT "\033[%dD"
#define ADDRESS "\033[%d;%dH"
#define GREEN "\033[0;40;32m"
#define NORMAL "\033[0m"
bool print (MooTermBuffer *buf)
{
for (guint i = 0; i < 1000; ++i)
moo_term_buffer_feed (buf, "kjhr jerhgjh erkjg hekrjghkerg ", -1);
return false;
}
bool print_random_hard (MooTerm *term)
{
MooTermBuffer *buf = term->priv->buffer;
guint width = buf_screen_width (buf);
guint height = buf_screen_height (buf);
guint row, col;
gboolean first_time = TRUE;
for (guint i = 0; i < 10000; ++i)
{
char r = 32 + (int) (94.0 * rand() / (RAND_MAX+1.0));
row = 1 + (int) (((double)height) * rand() / (RAND_MAX+1.0));
col = 1 + (int) (((double)width) * rand() / (RAND_MAX+1.0));
char *s = g_strdup_printf (ADDRESS "%c", row, col, r);
moo_term_buffer_feed (buf, s, -1);
g_free (s);
moo_term_force_update (term);
}
g_print ("buffer: %dx%d\nterm: %dx%d\n",
buf_total_height (buf), buf_screen_width (buf),
term_height (term), term_width (term));
gtk_main_quit ();
return false;
}
bool print_random_soft (MooTerm *term)
{
MooTermBuffer *buf = term->priv->buffer;
guint width = buf_screen_width (buf);
guint height = buf_screen_height (buf);
guint row, col;
gboolean first_time = TRUE;
char r = 32 + (int) (94.0 * rand() / (RAND_MAX+1.0));
row = 1 + (int) (((double)height) * rand() / (RAND_MAX+1.0));
col = 1 + (int) (((double)width) * rand() / (RAND_MAX+1.0));
char *s = g_strdup_printf (ADDRESS "%c", row, col, r);
moo_term_buffer_feed (buf, s, -1);
g_free (s);
return true;
}
int main (int argc, char *argv[]) int main (int argc, char *argv[])
{ {
gtk_init (&argc, &argv); gtk_init (&argc, &argv);
const char *cmd = CMD; char *cmd = NULL;
if (argc > 1) cmd = argv[1];
if (argc > 1)
{
cmd = g_strdup (argv[1]);
}
else
{
const char *dir = g_getenv ("HOME");
if (!dir)
dir = "/";
cmd = g_strdup_printf ("ls -R %s", dir);
}
GtkWidget *win = gtk_window_new (GTK_WINDOW_TOPLEVEL); GtkWidget *win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_widget_set_size_request (win, 400, 400); gtk_window_set_default_size (GTK_WINDOW (win), 400, 400);
GtkWidget *swin = gtk_scrolled_window_new (NULL, NULL); GtkWidget *swin = gtk_scrolled_window_new (NULL, NULL);
gtk_container_add (GTK_CONTAINER (win), swin); gtk_container_add (GTK_CONTAINER (win), swin);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swin), gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swin),
@ -113,17 +50,13 @@ int main (int argc, char *argv[])
MooTermBuffer *buf = moo_term_get_buffer (MOO_TERM (term)); MooTermBuffer *buf = moo_term_get_buffer (MOO_TERM (term));
g_object_set (buf, g_object_set (buf,
"am-mode", FALSE, "am-mode", TRUE,
"insert-mode", FALSE, "insert-mode", TRUE,
"cursor-visible", TRUE, "cursor-visible", TRUE,
NULL); NULL);
// for (guint i = 0; i < 1000; ++i) moo_term_fork_command (MOO_TERM (term), cmd, NULL, NULL);
// moo_term_buffer_feed (buf, "Hello there", -1); g_free (cmd);
// g_print ("%dx%d\n", buf_screen_width (buf), buf_total_height (buf));
// g_timeout_add (1000, (GSourceFunc) print, buf);
g_idle_add ((GSourceFunc) print_random_hard, term);
g_signal_connect (G_OBJECT (win), "destroy", gtk_main_quit, NULL); g_signal_connect (G_OBJECT (win), "destroy", gtk_main_quit, NULL);
gtk_main (); gtk_main ();

130
tests/termbuffer.cpp Normal file
View File

@ -0,0 +1,130 @@
//
// tests/mterm.cpp
//
// Copyright (C) 2004-2005 by Yevgen Muntyan <muntyan@math.tamu.edu>
//
// 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 of the License, or
// (at your option) any later version.
//
// See COPYING file that comes with this distribution.
//
#include <gtk/gtk.h>
#define MOOTERM_COMPILATION
#include "mooterm/mooterm-private.h"
#include <string.h>
#include <stdlib.h>
#ifndef __WIN32__
#define CMD "sh"
#else
#define CMD "gapw95.exe"
#endif
#define CLEAR "\033[H\033[2J"
#define HOME "\033[H"
#define PARM_RIGHT "\033[%dC"
#define PARM_LEFT "\033[%dD"
#define ADDRESS "\033[%d;%dH"
#define GREEN "\033[0;40;32m"
#define NORMAL "\033[0m"
bool print (MooTermBuffer *buf)
{
for (guint i = 0; i < 1000; ++i)
moo_term_buffer_feed (buf, "kjhr jerhgjh erkjg hekrjghkerg ", -1);
return false;
}
bool print_random_hard (MooTerm *term)
{
MooTermBuffer *buf = term->priv->buffer;
guint width = buf_screen_width (buf);
guint height = buf_screen_height (buf);
guint row, col;
gboolean first_time = TRUE;
for (guint i = 0; i < 10000; ++i)
{
char r = 32 + (int) (94.0 * rand() / (RAND_MAX+1.0));
row = 1 + (int) (((double)height) * rand() / (RAND_MAX+1.0));
col = 1 + (int) (((double)width) * rand() / (RAND_MAX+1.0));
char *s = g_strdup_printf (ADDRESS "%c", row, col, r);
moo_term_buffer_feed (buf, s, -1);
g_free (s);
moo_term_force_update (term);
}
g_print ("buffer: %dx%d\nterm: %dx%d\n",
buf_total_height (buf), buf_screen_width (buf),
term_height (term), term_width (term));
gtk_main_quit ();
return false;
}
bool print_random_soft (MooTerm *term)
{
MooTermBuffer *buf = term->priv->buffer;
guint width = buf_screen_width (buf);
guint height = buf_screen_height (buf);
guint row, col;
gboolean first_time = TRUE;
char r = 32 + (int) (94.0 * rand() / (RAND_MAX+1.0));
row = 1 + (int) (((double)height) * rand() / (RAND_MAX+1.0));
col = 1 + (int) (((double)width) * rand() / (RAND_MAX+1.0));
char *s = g_strdup_printf (ADDRESS "%c", row, col, r);
moo_term_buffer_feed (buf, s, -1);
g_free (s);
return true;
}
int main (int argc, char *argv[])
{
gtk_init (&argc, &argv);
const char *cmd = CMD;
if (argc > 1) cmd = argv[1];
GtkWidget *win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_widget_set_size_request (win, 400, 400);
GtkWidget *swin = gtk_scrolled_window_new (NULL, NULL);
gtk_container_add (GTK_CONTAINER (win), swin);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swin),
GTK_POLICY_NEVER,
GTK_POLICY_AUTOMATIC);
GtkWidget *term = GTK_WIDGET (g_object_new (MOO_TYPE_TERM, NULL));
gtk_container_add (GTK_CONTAINER (swin), term);
gtk_widget_show_all (win);
MooTermBuffer *buf = moo_term_get_buffer (MOO_TERM (term));
g_object_set (buf,
"am-mode", FALSE,
"insert-mode", FALSE,
"cursor-visible", TRUE,
NULL);
// for (guint i = 0; i < 1000; ++i)
// moo_term_buffer_feed (buf, "Hello there", -1);
// g_print ("%dx%d\n", buf_screen_width (buf), buf_total_height (buf));
// g_timeout_add (1000, (GSourceFunc) print, buf);
g_idle_add ((GSourceFunc) print_random_hard, term);
g_signal_connect (G_OBJECT (win), "destroy", gtk_main_quit, NULL);
gtk_main ();
}