diff --git a/src/conio/Common.gmake b/src/conio/Common.gmake
index d4cd441660a034a572f2da2d04a87e0a8ec87574..6dbe3fccfa0436fa0974f41a8fc00550b98f0243 100644
--- a/src/conio/Common.gmake
+++ b/src/conio/Common.gmake
@@ -3,6 +3,7 @@
 # XCURSES			= Use XCurses
 # NEED_CIOLIB		= Set flage suitable for using with ciolib
 # NO_X				= Don't use X version of ciolib
+# NEED_CTERM		= Use CTerm
 
 # You really should set this first.
 CONIO_SRC	?=	$(XPDEV)../conio/
@@ -41,6 +42,8 @@ endif
 CIOLIB_CFLAGS	+=	$(CURSES_CFLAGS)
 CIOLIB_LDFLAGS	+=	$(CURSES_LDFLAGS)
 
+CTERM_OBJS		+=	$(LIBODIR)/cterm.o
+
 ifdef NEED_CIOLIB
  CFLAGS +=	$(CIOLIB_CFLAGS)
  LDFLAGS	+=	$(CIOLIB_LDFLAGS)
@@ -51,11 +54,15 @@ ifdef UIFC_NEED_CIOLIB
  UIFC_LDFLAGS	+=	$(CIOLIB_LDFLAGS)
  UIFC_OBJS		+=	$(CIOLIB_OBJS)
 endif
-
 ifdef NEED_CURSES
  CFLAGS	+=	$(CURSES_CFLAGS)
  LDFLAGS	+=	$(CURSES_LDFLAGS)
 endif
+ifdef NEED_CTERM
+ CFLAGS	+=	$(CTERM_CFLAGS)
+ LDFLAGS	+=	$(CTERM_LDFLAGS)
+ OBJS	+=	$(CTERM_OBJS)
+endif
 
 vpath %.c $(CONIO_SRC)
 vpath %.cpp $(CONIO_SRC)
diff --git a/src/conio/cterm.c b/src/conio/cterm.c
new file mode 100644
index 0000000000000000000000000000000000000000..e86e9032b5b8f014f4439755c7b0a6ad027c7d7d
--- /dev/null
+++ b/src/conio/cterm.c
@@ -0,0 +1,605 @@
+#include <genwrap.h>
+#include <ciolib.h>
+#include <keys.h>
+
+#include "cterm.h"
+
+#define	BUFSIZE	2048
+
+struct terminal {
+	int	height;
+	int	width;
+	int	x;
+	int	y;
+	char *buffer;
+	int	attr;
+	int save_xpos;
+	int save_ypos;
+	char	escbuf[1024];
+	int	sequence;
+	char	musicbuf[1024];
+	int music;
+	char *scrollback;
+	int backpos;
+	int backlines;
+};
+
+static struct terminal term;
+
+/* const int tabs[11]={1,8,16,24,32,40,48,56,64,72,80}; */
+const int tabs[11]={9,17,25,33,41,49,57,65,73,80,80.1};
+
+void play_music(void)
+{
+	/* ToDo Music code parsing stuff */
+	term.music=0;
+}
+
+void scrolldown(void)
+{
+	char *buf;
+	int i,j;
+
+	buf=(char *)malloc(term.width*(term.height-1)*2);
+	gettext(term.x+1,term.y+1,term.x+term.width,term.y+term.height-1,buf);
+	puttext(term.x+1,term.y+2,term.x+term.width,term.y+term.height,buf);
+	j=0;
+	for(i=0;i<term.width;i++) {
+		buf[j++]=' ';
+		buf[j++]=term.attr;
+	}
+	puttext(term.x+1,term.y+1,term.x+term.width,term.y+1,buf);
+	free(buf);
+}
+
+void scrollup(void)
+{
+	char *buf;
+	int i,j;
+
+	term.backpos++;
+	if(term.scrollback!=NULL) {
+		if(term.backpos>term.backlines) {
+			memmove(term.scrollback,term.scrollback+term.width*2,term.width*2*(term.backlines-1));
+			term.backpos--;
+		}
+		gettext(term.x+1,term.y+1,term.x+term.width,term.y+1,term.scrollback+(term.backpos-1)*term.width*2);
+	}
+	buf=(char *)malloc(term.width*(term.height-1)*2);
+	gettext(term.x+1,term.y+2,term.x+term.width,term.y+term.height,buf);
+	puttext(term.x+1,term.y+1,term.x+term.width,term.y+term.height-1,buf);
+	j=0;
+	for(i=0;i<term.width;i++) {
+		buf[j++]=' ';
+		buf[j++]=term.attr;
+	}
+	puttext(term.x+1,term.y+term.height,term.x+term.width,term.y+term.height,buf);
+	free(buf);
+}
+
+void clear2bol(void)
+{
+	char *buf;
+	int i,j;
+
+	buf=(char *)malloc((wherex()+1)*2);
+	j=0;
+	for(i=1;i<=wherex();i++) {
+		buf[j++]=' ';
+		buf[j++]=term.attr;
+	}
+	puttext(term.x+1,term.y+wherey(),term.x+wherex(),term.y+wherey(),buf);
+	free(buf);
+}
+
+void clear2eol(void)
+{
+	char *buf;
+	int i,j;
+
+	buf=(char *)malloc((term.width-wherex()+1)*2);
+	j=0;
+	for(i=wherex();i<=term.width;i++) {
+		buf[j++]=' ';
+		buf[j++]=term.attr;
+	}
+	puttext(term.x+wherex(),term.y+wherey(),term.x+term.width,term.y+wherey(),buf);
+	free(buf);
+}
+
+void clearscreen(char attr)
+{
+	char *buf;
+	int x,y,j;
+
+	term.backpos+=term.height;
+	if(term.scrollback!=NULL) {
+		if(term.backpos>term.backlines) {
+			memmove(term.scrollback,term.scrollback+term.width*2*(term.backpos-term.backlines),term.width*2*(term.backlines-(term.backpos-term.backlines)));
+			term.backpos=term.backlines;
+		}
+		gettext(term.x+1,term.y+1,term.x+term.width,term.y+term.height,term.scrollback+(term.backpos-term.height)*term.width*2);
+	}
+	buf=(char *)malloc(term.width*(term.height)*2);
+	j=0;
+	for(x=0;x<term.width;x++) {
+		for(y=0;y<term.height;y++) {
+			buf[j++]=' ';
+			buf[j++]=attr;
+		}
+	}
+	puttext(term.x+1,term.y+1,term.x+term.width,term.y+term.height,buf);
+	free(buf);
+}
+
+void do_ansi(char *retbuf, int retsize)
+{
+	char	*p;
+	char	*p2;
+	char	tmp[1024];
+	int		i,j,k;
+	int		row,col;
+
+	switch(term.escbuf[0]) {
+		case '[':
+			/* ANSI stuff */
+			p=term.escbuf+strlen(term.escbuf)-1;
+			switch(*p) {
+				case '@':	/* Insert Char */
+					i=wherex();
+					j=wherey();
+					gettext(term.x+wherex(),term.y+wherey(),term.x+term.width-1,term.y+wherey(),tmp);
+					putch(' ');
+					puttext(term.x+wherex()+1,term.y+wherey(),term.x+term.width,term.y+wherey(),tmp);
+					gotoxy(i,j);
+					break;
+				case 'A':	/* Cursor Up */
+					i=atoi(term.escbuf+1);
+					if(i==0)
+						i=1;
+					i=wherey()-i;
+					if(i<1)
+						i=1;
+					gotoxy(wherex(),i);
+					break;
+				case 'B':	/* Cursor Down */
+					i=atoi(term.escbuf+1);
+					if(i==0)
+						i=1;
+					i=wherey()+i;
+					if(i>term.height)
+						i=term.height;
+					gotoxy(wherex(),i);
+					break;
+				case 'C':	/* Cursor Right */
+					i=atoi(term.escbuf+1);
+					if(i==0)
+						i=1;
+					i=wherex()+i;
+					if(i>term.width)
+						i=term.width;
+					gotoxy(i,wherey());
+					break;
+				case 'D':	/* Cursor Left */
+					i=atoi(term.escbuf+1);
+					if(i==0)
+						i=1;
+					i=wherex()-i;
+					if(i<1)
+						i=1;
+					gotoxy(i,wherey());
+					break;
+				case 'E':
+					i=atoi(term.escbuf+1);
+					if(i==0)
+						i=1;
+					i=wherey()+i;
+					for(j=0;j<i;j++)
+						putch('\n');
+					break;
+				case 'f':
+				case 'H':
+					row=1;
+					col=1;
+					*(p--)=0;
+					if(strlen(term.escbuf)>1) {
+						if((p=strtok(term.escbuf+1,";"))!=NULL) {
+							row=atoi(p);
+							if((p=strtok(NULL,";"))!=NULL) {
+								col=atoi(p);
+							}
+						}
+					}
+					if(row<1)
+						row=1;
+					if(col<1)
+						col=1;
+					if(row>term.height)
+						row=term.height;
+					if(col>term.width)
+						col=term.width;
+					gotoxy(col,row);
+					break;
+				case 'J':
+					i=atoi(term.escbuf+1);
+					switch(i) {
+						case 0:
+							clear2eol();
+							p2=(char *)malloc(term.width*2);
+							j=0;
+							for(i=0;i<term.width;i++) {
+								p2[j++]=' ';
+								p2[j++]=term.attr;
+							}
+							for(i=wherey()+1;i<=term.height;i++) {
+								puttext(term.x+1,term.y+i,term.x+term.width,term.y+i,p2);
+							}
+							free(p2);
+							break;
+						case 1:
+							clear2bol();
+							p2=(char *)malloc(term.width*2);
+							j=0;
+							for(i=0;i<term.width;i++) {
+								p2[j++]=' ';
+								p2[j++]=term.attr;
+							}
+							for(i=wherey()-1;i>=1;i--) {
+								puttext(term.x+1,term.y+i,term.x+term.width,term.y+i,p2);
+							}
+							free(p2);
+							break;
+						case 2:
+							clearscreen(term.attr);
+							gotoxy(1,1);
+							break;
+					}
+					break;
+				case 'K':
+					i=atoi(term.escbuf+1);
+					switch(i) {
+						case 0:
+							clear2eol();
+							break;
+						case 1:
+							clear2bol();
+							break;
+						case 2:
+							p2=(char *)malloc(term.width*2);
+							j=0;
+							for(i=0;i<term.width;i++) {
+								p2[j++]=' ';
+								p2[j++]=term.attr;
+							}
+							puttext(term.x+1,term.y+wherey(),term.x+term.width,term.y+wherey(),p2);
+							free(p2);
+							break;
+					}
+					break;
+				case 'L':
+					i=atoi(term.escbuf+1);
+					if(i==0)
+						i=1;
+					if(i>term.height-wherey())
+						i=term.height-wherey();
+					if(i<term.height-wherey()) {
+						p2=(char *)malloc((term.height-wherey()-i)*term.width*2);
+						gettext(term.x+1,term.y+wherey(),term.x+term.width,wherey()+(term.height-wherey()-i),p2);
+						puttext(term.x+1,term.y+wherey()+i,term.x+term.width,wherey()+(term.height-wherey()),p2);
+						j=0;
+						free(p2);
+					}
+					p2=(char *)malloc(term.width*2);
+					j=0;
+					for(k=0;k<term.width;k++) {
+						p2[j++]=' ';
+						p2[j++]=term.attr;
+					}
+					for(k-0;j<i;i++) {
+						puttext(term.x+1,term.y+i,term.x+term.width,term.y+i,p2);
+					}
+					free(p2);
+					break;
+				case 'M':
+				case 'N':
+					term.music=1;
+					break;
+				case 'P':	/* Delete char */
+					i=atoi(term.escbuf+1);
+					if(i==0)
+						i=1;
+					if(i>term.width-wherex())
+						i=term.width-wherex();
+					p2=(char *)malloc((term.width-wherex())*2);
+					gettext(term.x+wherex(),term.y+wherey(),term.x+term.width,term.y+wherey(),p2);
+					memmove(p2,p2+(i*2),(term.width-wherex()-i)*2);
+					for(i=(term.width-wherex())*2-2;i>=wherex();i-=2)
+						p2[i]=' ';
+					puttext(term.x+wherex(),term.y+wherey(),term.x+term.width,term.y+wherey(),p2);
+					break;
+				case 'S':
+					scrollup();
+					break;
+				case 'T':
+					scrolldown();
+					break;
+				case 'U':
+					clearscreen(7);
+					gotoxy(1,1);
+					break;
+				case 'Y':	/* ToDo? BananaCom Clear Line */
+					break;
+				case 'Z':
+					for(j=10;j>=0;j--) {
+						if(tabs[j]<wherex()) {
+							gotoxy(tabs[j],wherey());
+							break;
+						}
+					}
+					break;
+				case 'b':	/* ToDo?  Banana ANSI */
+					break;
+				case 'g':	/* ToDo?  VT100 Tabs */
+					break;
+				case 'h':	/* ToDo?  Scrolling regeion, word-wrap, doorway mode */
+					break;
+				case 'i':	/* ToDo?  Printing */
+					break;
+				case 'l':	/* ToDo?  Scrolling regeion, word-wrap, doorway mode */
+					break;
+				case 'm':
+					*(p--)=0;
+					p2=term.escbuf+1;
+					if(p2>p) {
+						term.attr=7;
+						break;
+					}
+					while((p=strtok(p2,";"))!=NULL) {
+						p2=NULL;
+						switch(atoi(p)) {
+							case 0:
+								term.attr=7;
+								break;
+							case 1:
+								term.attr|=8;
+								break;
+							case 2:
+								term.attr&=247;
+								break;
+							case 4:	/* Underscore */
+								break;
+							case 5:
+							case 6:
+								term.attr|=128;
+								break;
+							case 7:
+								i=term.attr&7;
+								j=term.attr&112;
+								term.attr &= 136;
+								term.attr |= j>>4;
+								term.attr |= i<<4;
+								break;
+							case 8:
+								j=term.attr&112;
+								term.attr&=112;
+								term.attr |= j>>4;
+								break;
+							case 30:
+								term.attr&=248;
+								break;
+							case 31:
+								term.attr&=248;
+								term.attr|=4;
+								break;
+							case 32:
+								term.attr&=248;
+								term.attr|=2;
+								break;
+							case 33:
+								term.attr&=248;
+								term.attr|=6;
+								break;
+							case 34:
+								term.attr&=248;
+								term.attr|=1;
+								break;
+							case 35:
+								term.attr&=248;
+								term.attr|=5;
+								break;
+							case 36:
+								term.attr&=248;
+								term.attr|=3;
+								break;
+							case 37:
+								term.attr&=248;
+								term.attr|=7;
+								break;
+							case 40:
+								term.attr&=143;
+								break;
+							case 41:
+								term.attr&=143;
+								term.attr|=4<<4;
+								break;
+							case 42:
+								term.attr&=143;
+								term.attr|=2<<4;
+								break;
+							case 43:
+								term.attr&=143;
+								term.attr|=6<<4;
+								break;
+							case 44:
+								term.attr&=143;
+								term.attr|=1<<4;
+								break;
+							case 45:
+								term.attr&=143;
+								term.attr|=5<<4;
+								break;
+							case 46:
+								term.attr&=143;
+								term.attr|=3<<4;
+								break;
+							case 47:
+								term.attr&=143;
+								term.attr|=7<<4;
+								break;
+						}
+					}
+					textattr(term.attr);
+					break;
+				case 'n':
+					i=atoi(term.escbuf+1);
+					switch(i) {
+						case 6:
+							sprintf(tmp,"%c[%d;%dR",27,wherey(),wherex());
+							if(strlen(retbuf)+strlen(tmp) < retsize)
+								strcat(retbuf,tmp);
+							break;
+						case 255:
+							sprintf(tmp,"%c[%d;%dR",27,term.height,term.width);
+							if(strlen(retbuf)+strlen(tmp) < retsize)
+								strcat(retbuf,tmp);
+							break;
+					}
+					break;
+				case 'p': /* ToDo?  ANSI keyboard reassignment */
+					break;
+				case 'q': /* ToDo?  VT100 keyboard lights */
+					break;
+				case 'r': /* ToDo?  Scrolling reigon */
+					break;
+				case 's':
+					term.save_xpos=wherex();
+					term.save_ypos=wherey();
+					break;
+				case 'u':
+					if(term.save_ypos>0 && term.save_ypos<=term.height
+							&& term.save_xpos>0 && term.save_xpos<=term.width) {
+						gotoxy(term.save_xpos,term.save_ypos);
+					}
+					break;
+				case 'y':	/* ToDo?  VT100 Tests */
+					break;
+				case 'z':	/* ToDo?  Reset */
+					break;
+			}
+			break;
+		case 'D':
+			scrollup();
+			break;
+		case 'M':
+			scrolldown();
+			break;
+		case 'c':
+			/* ToDo: Reset Terminal */
+			break;
+	}
+	term.escbuf[0]=0;
+	term.sequence=0;
+}
+
+void cterm_init(int height, int width, int xpos, int ypos, int backlines, unsigned char *scrollback)
+{
+	term.x=xpos;
+	term.y=ypos;
+	term.height=height;
+	term.width=width;
+	term.attr=7;
+	term.save_xpos=0;
+	term.save_ypos=0;
+	term.escbuf[0]=0;
+	term.sequence=0;
+	term.music=0;
+	term.backpos=0;
+	term.backlines=backlines;
+	term.scrollback=scrollback;
+	if(term.scrollback!=NULL)
+		memset(term.scrollback,0,term.width*2*term.backlines);
+	textattr(term.attr);
+	_setcursortype(_NORMALCURSOR);
+	window(term.x+1,term.y+1,term.x+term.width,term.y+term.height);
+	clrscr();
+	gotoxy(1,1);
+}
+
+char *cterm_write(unsigned char *buf, int buflen, char *retbuf, int retsize)
+{
+	unsigned char ch[2];
+	unsigned char prn[BUFSIZE];
+	int	key;
+	int i,j,k;
+	char	*ret;
+
+	retbuf[0]=0;
+	switch(buflen) {
+		case 0:
+			break;
+		default:
+			prn[0]=0;
+			for(j=0;j<buflen;j++) {
+				ch[0]=buf[j];
+				if(term.sequence) {
+					strcat(term.escbuf,ch);
+					if((ch[0]>='@' && ch[0]<='Z')
+							|| (ch[0]>='a' && ch[0]<='z')) {
+						do_ansi(retbuf, retsize);
+					}
+				}
+				else if (term.music) {
+					strcat(term.musicbuf,ch);
+					if(ch[0]==14)
+						play_music();
+				}
+				else {
+					switch(buf[j]) {
+						case 0:
+							break;
+						case 7:			/* Beep */
+							cputs(prn);
+							prn[0]=0;
+							#ifdef __unix__
+								putch(7);
+							#else
+								MessageBeep(MB_OK);
+							#endif
+							break;
+						case 12:		/* ^L - Clear screen */
+							cputs(prn);
+							prn[0]=0;
+							clearscreen(term.attr);
+							gotoxy(1,1);
+							break;
+						case 27:		/* ESC */
+							cputs(prn);
+							prn[0]=0;
+							term.sequence=1;
+							break;
+						case '\t':
+							cputs(prn);
+							prn[0]=0;
+							for(k=0;k<11;k++) {
+								if(tabs[k]>wherex()) {
+									gotoxy(tabs[k],wherey());
+									break;
+								}
+							}
+							break;
+						default:
+							strcat(prn,ch);
+					}
+				}
+			}
+			cputs(prn);
+			prn[0]=0;
+			break;
+	}
+	return(retbuf);
+}
+
+void cterm_end(void)
+{
+	/* Nothing to be done here at the moment */
+}
diff --git a/src/conio/cterm.h b/src/conio/cterm.h
new file mode 100644
index 0000000000000000000000000000000000000000..9db0d68aa972e0e7ba1a9d8659b0a2d183556518
--- /dev/null
+++ b/src/conio/cterm.h
@@ -0,0 +1,14 @@
+#ifndef _TERM_H_
+#define _TERM_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+void cterm_init(int height, int width, int xpos, int ypos, int backlines, unsigned char *scrollback);
+char *cterm_write(unsigned char *buf, int buflen, char *retbuf, int retsize);
+void cterm_end(void);
+#ifdef __cplusplus
+}
+#endif
+
+#endif