A small demo about how to use GTK label as a simple console. To compile GTK program, `pkg-config gtk+-2.0 --cflags --libs` should finally be somewhere in the compiler command line in the bash-like shell.

#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include <string.h>
#define MX 41
#define MY 12

int keyb [MX], quit;

gint key_press_event (GtkWidget *widget, GdkEventKey *event)
{
	int i = MX - 1;

	if (event->keyval && !keyb [MX - 1]) {
		for (; i; i--) keyb [i] = keyb [i - 1];
		*keyb = event->keyval;
	}
	return 1;
}

gint delete_event (GtkWidget *widget, gpointer data)
{
	widget = widget;
	data = data;
	return 0;
}

void destroy (GtkWidget *widget, gpointer data)
{
	widget = widget;
	data = data;
	quit = 1;
}

int main (int argc, char **argv)
{
	char buf [MY] [MX];
	int x = 0, y = 0, i = 0, j;
	GdkColor white = {0, 0xffff, 0xffff, 0xffff},
		blue = {0, 0, 0, 0xffff};
	GtkWidget *window, *label;

	gtk_init (&argc, &argv);
	window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
	gtk_widget_set_size_request (window, 800, 500);
	gtk_window_set_title (GTK_WINDOW (window), "GTK Label");
	gtk_window_set_resizable (GTK_WINDOW (window), 0);
	gtk_container_set_border_width (GTK_CONTAINER (window), 10);
	gtk_widget_modify_bg (window, GTK_STATE_NORMAL, &white); 
	g_signal_connect (window, "delete_event", 
		G_CALLBACK (delete_event), NULL);
	g_signal_connect (window, "destroy", G_CALLBACK (destroy), NULL);
	gtk_widget_set_events (window, GDK_KEY_PRESS_MASK);
	g_signal_connect (G_OBJECT (window), "key_press_event",
		G_CALLBACK (key_press_event), NULL);
	label = gtk_label_new ("");
	gtk_container_add (GTK_CONTAINER (window), label);
	gtk_widget_modify_font (label,
		pango_font_description_from_string ("dejavu sans mono 24"));
	gtk_widget_modify_fg (label, GTK_STATE_NORMAL, &blue);
	gtk_widget_show_all (window);
	for (memset (*buf, ' ', MX * MY); i < MY; i++)
		buf [i] [MX - 1] = '\n';
	buf [MY - 1] [MX - 1] = 0;
	for (**buf = '_'; !quit; ) {
		if (*keyb) {
			for (i = 0; keyb [i] && i < MX; i++);
			if (keyb [--i] >= 0x020 && keyb [i] < 0x0b0) {
				buf [y] [x] = keyb [i];
				if (x < MX - 2) x++;
			} else
				buf [y] [x] = ' ';
			switch (keyb [i]) {
				case GDK_Left:
					x && x--;
					break;
				case GDK_Right:
					if (x < MX - 2) x++;
					break;
				case GDK_Up:
					y && y--;
					break;
				case GDK_Return:
					x = 0;
				case GDK_Down:
					if (y < MY - 1) y++;
					break;
			}
			keyb [i] = 0;
			buf [y] [x] = '_';
			gtk_label_set_text (GTK_LABEL (label), *buf);
		}
		g_usleep (100000l);
		while (g_main_context_iteration (NULL, 0));
	}
	return 0;
}