From 4d715fd9ddab04c309899d4c0901a371da49ad80 Mon Sep 17 00:00:00 2001
From: Patrik Stridvall <ps@leissner.se>
Date: Tue, 23 Nov 1999 23:43:29 +0000
Subject: [PATCH] Improved the stubs.

---
 graphics/ttydrv/Makefile.in |  11 +-
 graphics/ttydrv/bitblt.c    |  58 +++++++
 graphics/ttydrv/bitmap.c    |  39 ++++-
 graphics/ttydrv/brush.c     |  22 +++
 graphics/ttydrv/clipping.c  |  21 +++
 graphics/ttydrv/font.c      |  89 ++++++++++
 graphics/ttydrv/graphics.c  | 332 ++++++++++++++++++++++++++++++++++++
 graphics/ttydrv/init.c      | 125 +++++++++-----
 graphics/ttydrv/objects.c   |  93 ++++++++++
 graphics/ttydrv/oembitmap.c |  40 +++++
 graphics/ttydrv/palette.c   |  65 ++++++-
 graphics/ttydrv/pen.c       |  22 +++
 graphics/ttydrv/text.c      |  58 +++++++
 include/ttydrv.h            |  78 ++++++++-
 windows/ttydrv/desktop.c    |  21 +++
 windows/ttydrv/main.c       |   5 +
 windows/ttydrv/monitor.c    |  65 ++++++-
 windows/ttydrv/wnd.c        | 151 +++++++++++++++-
 18 files changed, 1237 insertions(+), 58 deletions(-)
 create mode 100644 graphics/ttydrv/bitblt.c
 create mode 100644 graphics/ttydrv/brush.c
 create mode 100644 graphics/ttydrv/clipping.c
 create mode 100644 graphics/ttydrv/font.c
 create mode 100644 graphics/ttydrv/graphics.c
 create mode 100644 graphics/ttydrv/objects.c
 create mode 100644 graphics/ttydrv/oembitmap.c
 create mode 100644 graphics/ttydrv/pen.c
 create mode 100644 graphics/ttydrv/text.c

diff --git a/graphics/ttydrv/Makefile.in b/graphics/ttydrv/Makefile.in
index d667c9fa041..ee2454bc280 100644
--- a/graphics/ttydrv/Makefile.in
+++ b/graphics/ttydrv/Makefile.in
@@ -6,9 +6,18 @@ VPATH     = @srcdir@
 MODULE    = ttydrv
 
 C_SRCS = \
+	bitblt.c \
 	bitmap.c \
+	brush.c \
+	clipping.c \
+	font.c \
+	graphics.c \
 	init.c \
-	palette.c
+	objects.c \
+	oembitmap.c \
+	palette.c \
+	pen.c \
+	text.c
 
 all: $(MODULE).o
 
diff --git a/graphics/ttydrv/bitblt.c b/graphics/ttydrv/bitblt.c
new file mode 100644
index 00000000000..757af0b1907
--- /dev/null
+++ b/graphics/ttydrv/bitblt.c
@@ -0,0 +1,58 @@
+/*
+ * TTY DC bit blit
+ *
+ * Copyright 1999 Patrik Stridvall
+ */
+
+#include "dc.h"
+#include "debugtools.h"
+#include "pen.h"
+#include "ttydrv.h"
+
+DEFAULT_DEBUG_CHANNEL(ttydrv)
+
+/***********************************************************************
+ *		TTYDRV_DC_BitBlt
+ */
+BOOL TTYDRV_DC_BitBlt(DC *dcDst, INT xDst, INT yDst,
+		      INT width, INT height, DC *dcSrc,
+		      INT xSrc, INT ySrc, DWORD rop)
+{
+  FIXME("(%p, %d, %d, %d, %d, %p, %d, %d, %lu): stub\n",
+	dcDst, xDst, yDst, width, height, 
+        dcSrc, xSrc, ySrc, rop
+  );
+
+  return TRUE;
+}
+
+/***********************************************************************
+ *		TTYDRV_DC_PatBlt
+ */
+BOOL TTYDRV_DC_PatBlt(DC *dc, INT left, INT top,
+		      INT width, INT height, DWORD rop)
+{
+  FIXME("(%p, %d, %d, %d, %d, %lu): stub\n",
+	dc, left, top, width, height, rop
+  );
+
+
+  return TRUE;
+}
+
+/***********************************************************************
+ *		TTYDRV_DC_StretchBlt
+ */
+BOOL TTYDRV_DC_StretchBlt(DC *dcDst, INT xDst, INT yDst,
+			  INT widthDst, INT heightDst,
+			  DC *dcSrc, INT xSrc, INT ySrc,
+			  INT widthSrc, INT heightSrc, DWORD rop)
+{
+  FIXME("(%p, %d, %d, %d, %d, %p, %d, %d, %d, %d, %lu): stub\n",
+	dcDst, xDst, yDst, widthDst, heightDst,
+	dcSrc, xSrc, ySrc, widthSrc, heightSrc, rop
+  );
+
+  return TRUE;
+}
+
diff --git a/graphics/ttydrv/bitmap.c b/graphics/ttydrv/bitmap.c
index 94c3cd896be..a6be6c8f859 100644
--- a/graphics/ttydrv/bitmap.c
+++ b/graphics/ttydrv/bitmap.c
@@ -4,10 +4,13 @@
  * Copyright 1999 Patrik Stridvall
  */
 
-#include "dc.h"
 #include "bitmap.h"
+#include "dc.h"
+#include "debugtools.h"
 #include "ttydrv.h"
 
+DEFAULT_DEBUG_CHANNEL(ttydrv)
+
 /**********************************************************************
  *		TTYDRV_BITMAP_CreateDIBSection
  */
@@ -54,3 +57,37 @@ INT TTYDRV_BITMAP_GetDIBits(
 void TTYDRV_BITMAP_DeleteDIBSection(BITMAPOBJ *bmp)
 {
 }
+
+/***********************************************************************
+ *		TTYDRV_DC_CreateBitmap
+ */
+BOOL TTYDRV_DC_CreateBitmap(HBITMAP hbitmap)
+{
+  FIXME("(0x%04x): stub\n", hbitmap);
+
+  return TRUE;
+}
+
+/***********************************************************************
+ *		TTYDRV_DC_BITMAP_DeleteObject
+ */
+BOOL TTYDRV_DC_BITMAP_DeleteObject(HBITMAP hbitmap, BITMAPOBJ *bitmap)
+{
+  FIXME("(0x%04x, %p): stub\n", hbitmap, bitmap);
+
+  return TRUE;
+}
+
+/***********************************************************************
+ *		TTYDRV_DC_BITMAP_SelectObject
+ */
+HBITMAP TTYDRV_DC_BITMAP_SelectObject(DC *dc, HBITMAP hbitmap, BITMAPOBJ *bitmap)
+{
+  FIXME("(%p, 0x%04x, %p): stub\n", dc, hbitmap, bitmap);
+
+  if(!(dc->w.flags & DC_MEMORY)) 
+    return NULL;
+
+  return NULL;
+}
+
diff --git a/graphics/ttydrv/brush.c b/graphics/ttydrv/brush.c
new file mode 100644
index 00000000000..23df2f0f620
--- /dev/null
+++ b/graphics/ttydrv/brush.c
@@ -0,0 +1,22 @@
+/*
+ * TTY DC brush
+ *
+ * Copyright 1999 Patrik Stridvall
+ */
+
+#include "brush.h"
+#include "dc.h"
+#include "debugtools.h"
+#include "ttydrv.h"
+
+DEFAULT_DEBUG_CHANNEL(ttydrv)
+
+/***********************************************************************
+ *		TTYDRV_DC_BRUSH_SelectObject
+ */
+HBRUSH TTYDRV_DC_BRUSH_SelectObject(DC *dc, HBRUSH hbrush, BRUSHOBJ *brush)
+{
+  FIXME("(%p, 0x%08x, %p): stub\n", dc, hbrush, brush);
+
+  return NULL;
+}
diff --git a/graphics/ttydrv/clipping.c b/graphics/ttydrv/clipping.c
new file mode 100644
index 00000000000..184b3faa1db
--- /dev/null
+++ b/graphics/ttydrv/clipping.c
@@ -0,0 +1,21 @@
+/*
+ * TTY DC clipping
+ *
+ * Copyright 1999 Patrik Stridvall
+ */
+
+#include "dc.h"
+#include "debugtools.h"
+#include "ttydrv.h"
+
+DEFAULT_DEBUG_CHANNEL(ttydrv)
+
+/***********************************************************************
+ *		TTYDRV_DC_SetDeviceClipping
+ */
+void TTYDRV_DC_SetDeviceClipping(DC *dc)
+{
+  FIXME("(%p): stub\n", dc);
+}
+
+
diff --git a/graphics/ttydrv/font.c b/graphics/ttydrv/font.c
new file mode 100644
index 00000000000..c0d900be62f
--- /dev/null
+++ b/graphics/ttydrv/font.c
@@ -0,0 +1,89 @@
+/*
+ * TTY font driver
+ *
+ * Copyright 1999 Patrik Stridvall
+ */
+#include "dc.h"
+#include "debugtools.h"
+#include "font.h"
+#include "ttydrv.h"
+#include "wingdi.h"
+
+DEFAULT_DEBUG_CHANNEL(ttydrv)
+
+/***********************************************************************
+ *		TTYDRV_DC_GetCharWidth
+ */
+BOOL TTYDRV_DC_GetCharWidth(DC *dc, UINT firstChar, UINT lastChar,
+			    LPINT buffer)
+{
+  UINT c;
+  TTYDRV_PDEVICE *physDev = (TTYDRV_PDEVICE *) dc->physDev;
+
+  FIXME("(%p, %u, %u, %p): semistub\n", dc, firstChar, lastChar, buffer);
+
+  for(c=firstChar; c<=lastChar; c++) {
+    buffer[c-firstChar] = physDev->cellWidth;
+  }
+
+  return TRUE;
+}
+
+/***********************************************************************
+ *		TTYDRV_DC_GetTextExtentPoint
+ */
+BOOL TTYDRV_DC_GetTextExtentPoint(DC *dc, LPCSTR str, INT count,
+				  LPSIZE size)
+{
+  TTYDRV_PDEVICE *physDev = (TTYDRV_PDEVICE *) dc->physDev;
+
+  FIXME("(%p, %s, %d, %p): semistub\n", dc, debugstr_an(str,count), count, size);
+
+  size->cx = count * physDev->cellWidth;
+  size->cy = physDev->cellHeight;
+
+  return TRUE;
+}
+
+/***********************************************************************
+ *		TTYDRV_DC_GetTextMetrics
+ */
+BOOL TTYDRV_DC_GetTextMetrics(DC *dc, LPTEXTMETRICA lptm)
+{
+  TTYDRV_PDEVICE *physDev = (TTYDRV_PDEVICE *) dc->physDev;
+
+  FIXME("(%p, %p): stub\n", dc, lptm);
+
+  lptm->tmHeight = physDev->cellHeight;
+  lptm->tmAscent = 0;
+  lptm->tmDescent = 0;
+  lptm->tmInternalLeading = 0;
+  lptm->tmExternalLeading = 0;
+  lptm->tmAveCharWidth = physDev->cellWidth; 
+  lptm->tmMaxCharWidth = physDev->cellWidth;
+  lptm->tmWeight = FW_MEDIUM;
+  lptm->tmOverhang = 0;
+  lptm->tmDigitizedAspectX = physDev->cellWidth;
+  lptm->tmDigitizedAspectY = physDev->cellHeight;
+  lptm->tmFirstChar = 32;
+  lptm->tmLastChar = 255;
+  lptm->tmDefaultChar = 0;
+  lptm->tmBreakChar = 32;
+  lptm->tmItalic = FALSE;
+  lptm->tmUnderlined = FALSE;
+  lptm->tmStruckOut = FALSE;
+  lptm->tmPitchAndFamily = TMPF_FIXED_PITCH|TMPF_DEVICE;
+  lptm->tmCharSet = ANSI_CHARSET;
+
+  return TRUE;
+}
+
+/***********************************************************************
+ *		TTYDRV_DC_FONT_SelectObject
+ */
+HFONT TTYDRV_DC_FONT_SelectObject(DC* dc, HFONT hfont, FONTOBJ *font)
+{
+  FIXME("(%p, 0x%08x, %p): stub\n", dc, hfont, font);
+
+  return NULL;
+}
diff --git a/graphics/ttydrv/graphics.c b/graphics/ttydrv/graphics.c
new file mode 100644
index 00000000000..aee68104ec8
--- /dev/null
+++ b/graphics/ttydrv/graphics.c
@@ -0,0 +1,332 @@
+/*
+ * TTY DC graphics
+ *
+ * Copyright 1999 Patrik Stridvall
+ */
+
+#include "config.h"
+
+#include "dc.h"
+#include "debugtools.h"
+#include "ttydrv.h"
+
+DEFAULT_DEBUG_CHANNEL(ttydrv)
+
+/***********************************************************************
+ *		TTYDRV_DC_Arc
+ */
+BOOL TTYDRV_DC_Arc(DC *dc, INT left, INT top, INT right, INT bottom,
+		   INT xstart, INT ystart, INT xend, INT yend)
+{
+  FIXME("(%p, %d, %d, %d, %d, %d, %d, %d, %d): stub\n",
+	dc, left, top, right, bottom, xstart, ystart, xend, yend);
+
+  return TRUE;
+}
+
+/***********************************************************************
+ *		TTYDRV_DC_Chord
+ */
+BOOL TTYDRV_DC_Chord(DC *dc, INT left, INT top, INT right, INT bottom,
+		     INT xstart, INT ystart, INT xend, INT yend)
+{
+  FIXME("(%p, %d, %d, %d, %d, %d, %d, %d, %d): stub\n",
+	dc, left, top, right, bottom, xstart, ystart, xend, yend);
+
+  return TRUE;
+}
+
+/***********************************************************************
+ *		TTYDRV_DC_Ellipse
+ */
+BOOL TTYDRV_DC_Ellipse(DC *dc, INT left, INT top, INT right, INT bottom)
+{
+  FIXME("(%p, %d, %d, %d, %d): stub\n",
+	dc, left, top, right, bottom);
+
+  return TRUE;
+}
+
+/***********************************************************************
+ *		TTYDRV_DC_ExtFloodFill
+ */
+BOOL TTYDRV_DC_ExtFloodFill(DC *dc, INT x, INT y,
+			    COLORREF color, UINT fillType)
+{
+  FIXME("(%p, %d, %d, 0x%08lx, %u): stub\n", dc, x, y, color, fillType);
+
+  return TRUE;
+}
+
+/***********************************************************************
+ *		TTYDRV_DC_GetPixel
+ */
+COLORREF TTYDRV_DC_GetPixel(DC *dc, INT x, INT y)
+{
+  FIXME("(%p, %d, %d): stub\n", dc, x, y);
+
+  return RGB(0,0,0); /* FIXME: Always returns black */
+}
+
+/***********************************************************************
+ *		TTYDRV_DC_LineTo
+ */
+BOOL TTYDRV_DC_LineTo(DC *dc, INT x, INT y)
+{
+#ifdef HAVE_LIBCURSES
+  TTYDRV_PDEVICE *physDev = (TTYDRV_PDEVICE *) dc->physDev;
+  INT row1, col1, row2, col2;
+
+  TRACE("(%p, %d, %d)\n", dc, x, y);
+
+  row1 = (dc->w.DCOrgY + XLPTODP(dc, dc->w.CursPosY)) / physDev->cellHeight;
+  col1 = (dc->w.DCOrgX + XLPTODP(dc, dc->w.CursPosX)) / physDev->cellWidth;
+  row2 = (dc->w.DCOrgY + XLPTODP(dc, y)) / physDev->cellHeight;
+  col2 = (dc->w.DCOrgX + XLPTODP(dc, x)) / physDev->cellWidth;
+
+  if(row1 > row2) {
+    INT tmp = row1;
+    row1 = row2;
+    row2 = tmp; 
+  } 
+
+  if(col1 > col2) {
+    INT tmp = col1;
+    col1 = col2;
+    col2 = tmp; 
+  } 
+
+  wmove(physDev->window, row1, col1);
+  if(col1 == col2) {
+    wvline(physDev->window, '|', row2-row1);
+  } else if(row1 == row2) {
+    whline(physDev->window, '-', col2-col1);
+  } else {
+    FIXME("Diagonal line drawing not yet supported\n");
+  }
+  wrefresh(physDev->window);
+
+  dc->w.CursPosX = x;
+  dc->w.CursPosY = y;
+
+  return TRUE;
+#else /* defined(HAVE_LIBCURSES) */
+  FIXME("(%p, %d, %d): stub\n", dc, x, y);
+
+  return TRUE;
+#endif /* defined(HAVE_LIBCURSES) */
+}
+
+/***********************************************************************
+ *		TTYDRV_DC_MoveToEx
+ */
+BOOL TTYDRV_DC_MoveToEx(DC *dc, INT x, INT y, LPPOINT pt)
+{
+  TRACE("(%p, %d, %d, %p)\n", dc, x, y, pt);
+
+  if(pt) {
+    pt->x = dc->w.CursPosX;
+    pt->y = dc->w.CursPosY;
+  }
+  
+  dc->w.CursPosX = x;
+  dc->w.CursPosY = y;
+
+  return TRUE;
+}
+
+/***********************************************************************
+ *		TTYDRV_DC_PaintRgn
+ */
+BOOL TTYDRV_DC_PaintRgn(DC *dc, HRGN hrgn)
+{
+  FIXME("(%p, 0x%04x): stub\n", dc, hrgn);
+
+  return TRUE;
+}
+
+/***********************************************************************
+ *		TTYDRV_DC_Pie
+ */
+BOOL TTYDRV_DC_Pie(DC *dc, INT left, INT top, INT right, INT bottom,
+		   INT xstart, INT ystart, INT xend, INT yend)
+{
+  FIXME("(%p, %d, %d, %d, %d, %d, %d, %d, %d): stub\n",
+	dc, left, top, right, bottom, xstart, ystart, xend, yend);
+
+  return TRUE;
+}
+
+/***********************************************************************
+ *		TTYDRV_DC_PolyBezier
+ */
+BOOL TTYDRV_DC_PolyBezier(DC *dc, POINT start,
+			  const POINT* BezierPoints, DWORD count)
+{
+  FIXME("(%p, {%ld, %ld}, %p, %lu): stub\n",
+	dc, start.x, start.y, BezierPoints, count);
+
+  return TRUE;
+}
+
+/***********************************************************************
+ *		TTYDRV_DC_Polygon
+ */
+BOOL TTYDRV_DC_Polygon(DC *dc, const POINT* pt, INT count)
+{
+  FIXME("(%p, %p, %d): stub\n", dc, pt, count);
+
+  return TRUE;
+}
+
+/***********************************************************************
+ *		TTYDRV_DC_Polyline
+ */
+BOOL TTYDRV_DC_Polyline(DC *dc, const POINT* pt, INT count)
+{
+  FIXME("(%p, %p, %d): stub\n", dc, pt, count);
+
+  return TRUE;
+}
+
+/***********************************************************************
+ *		TTYDRV_DC_PolyPolygon
+ */
+BOOL TTYDRV_DC_PolyPolygon(DC *dc, const POINT* pt, const INT* counts, UINT polygons)
+{
+  FIXME("(%p, %p, %p, %u): stub\n", dc, pt, counts, polygons);
+
+  return TRUE;
+}
+
+/***********************************************************************
+ *		TTYDRV_DC_PolyPolyline
+ */
+BOOL TTYDRV_DC_PolyPolyline(DC *dc, const POINT* pt, const DWORD* counts, DWORD polylines)
+{
+  FIXME("(%p, %p, %p, %lu): stub\n", dc, pt, counts, polylines);
+  
+  return TRUE;
+}
+
+/***********************************************************************
+ *		TTYDRV_DC_Rectangle
+ */
+BOOL TTYDRV_DC_Rectangle(DC *dc, INT left, INT top, INT right, INT bottom)
+{
+#ifdef HAVE_LIBCURSES
+  TTYDRV_PDEVICE *physDev = (TTYDRV_PDEVICE *) dc->physDev;
+  INT row1, col1, row2, col2;
+
+  TRACE("(%p, %d, %d, %d, %d)\n", dc, left, top, right, bottom);
+
+  row1 = (dc->w.DCOrgY + XLPTODP(dc, top)) / physDev->cellHeight;
+  col1 = (dc->w.DCOrgX + XLPTODP(dc, left)) / physDev->cellWidth;
+  row2 = (dc->w.DCOrgY + XLPTODP(dc, bottom)) / physDev->cellHeight;
+  col2 = (dc->w.DCOrgX + XLPTODP(dc, right)) / physDev->cellWidth;
+
+  if(row1 > row2) {
+    INT tmp = row1;
+    row1 = row2;
+    row2 = tmp; 
+  } 
+  if(col1 > col2) {
+    INT tmp = col1;
+    col1 = col2;
+    col2 = tmp; 
+  } 
+
+  wmove(physDev->window, row1, col1);
+  whline(physDev->window, '-', col2-col1);
+
+  wmove(physDev->window, row1, col2);
+  wvline(physDev->window, '|', row2-row1);
+
+  wmove(physDev->window, row2, col1);
+  whline(physDev->window, '-', col2-col1);
+
+  wmove(physDev->window, row1, col1);
+  wvline(physDev->window, '|', row2-row1);
+
+  mvwaddch(physDev->window, row1, col1, '+');
+  mvwaddch(physDev->window, row1, col2, '+');
+  mvwaddch(physDev->window, row2, col2, '+');
+  mvwaddch(physDev->window, row2, col1, '+');
+
+  wrefresh(physDev->window);
+
+  return TRUE;
+#else /* defined(HAVE_LIBCURSES) */
+  FIXME("(%p, %d, %d, %d, %d): stub\n", dc, left, top, right, bottom);
+
+  return TRUE;
+#endif /* defined(HAVE_LIBCURSES) */
+}
+
+/***********************************************************************
+ *		TTYDRV_DC_RoundRect
+ */
+BOOL TTYDRV_DC_RoundRect(DC *dc, INT left, INT top, INT right,
+			 INT bottom, INT ell_width, INT ell_height)
+{
+  FIXME("(%p, %d, %d, %d, %d, %d, %d): stub\n", 
+	dc, left, top, right, bottom, ell_width, ell_height);
+  
+  return TRUE;
+}
+
+/***********************************************************************
+ *		TTYDRV_DC_SetBkColor
+ */
+COLORREF TTYDRV_DC_SetBkColor(DC *dc, COLORREF color)
+{
+  COLORREF oldColor;
+
+  TRACE("(%p, 0x%08lx)\n", dc, color);  
+
+  oldColor = dc->w.backgroundColor;
+  dc->w.backgroundColor = color;
+
+  return oldColor;
+}
+
+/***********************************************************************
+ *		TTYDRV_DC_SetPixel
+ */
+COLORREF TTYDRV_DC_SetPixel(DC *dc, INT x, INT y, COLORREF color)
+{
+#ifdef HAVE_LIBCURSES
+  TTYDRV_PDEVICE *physDev = (TTYDRV_PDEVICE *) dc->physDev;
+  INT row, col;
+
+  TRACE("(%p, %d, %d, 0x%08lx)\n", dc, x, y, color);
+
+  row = (dc->w.DCOrgY + XLPTODP(dc, y)) / physDev->cellHeight;
+  col = (dc->w.DCOrgX + XLPTODP(dc, x)) / physDev->cellWidth;
+
+  mvwaddch(physDev->window, row, col, '.');
+  wrefresh(physDev->window);
+
+  return RGB(0,0,0); /* FIXME: Always returns black */
+#else /* defined(HAVE_LIBCURSES) */
+  FIXME("(%p, %d, %d, 0x%08lx): stub\n", dc, x, y, color);
+
+  return RGB(0,0,0); /* FIXME: Always returns black */
+#endif /* defined(HAVE_LIBCURSES) */
+}
+
+/***********************************************************************
+ *		TTYDRV_DC_SetTextColor
+ */
+COLORREF TTYDRV_DC_SetTextColor(DC *dc, COLORREF color)
+{
+  COLORREF oldColor;
+
+  TRACE("(%p, 0x%08lx)\n", dc, color);
+  
+  oldColor = dc->w.textColor;
+  dc->w.textColor = color;
+  
+  return oldColor;
+}
+
diff --git a/graphics/ttydrv/init.c b/graphics/ttydrv/init.c
index 122b6d2f2e6..ae3cdf122f1 100644
--- a/graphics/ttydrv/init.c
+++ b/graphics/ttydrv/init.c
@@ -4,85 +4,89 @@
  * Copyright 1998 Patrik Stridvall
  */
 
+#include "config.h"
+
 #include "gdi.h"
 #include "bitmap.h"
 #include "color.h"
 #include "dc.h"
-#include "debugtools.h"
 #include "heap.h"
+#include "monitor.h"
 #include "palette.h"
 #include "ttydrv.h"
+#include "debugtools.h"
 
 DEFAULT_DEBUG_CHANNEL(ttydrv)
 
 static const DC_FUNCTIONS TTYDRV_DC_Driver =
 {
   NULL,                /* pAbortDoc */
-  NULL,                /* pArc */
-  NULL,                /* pBitBlt */
+  TTYDRV_DC_Arc,       /* pArc */
+  TTYDRV_DC_BitBlt,    /* pBitBlt */
   NULL,                /* pBitmapBits */
-  NULL,                /* pChord */
-  NULL,                /* pCreateBitmap */
+  TTYDRV_DC_Chord,     /* pChord */
+  TTYDRV_DC_CreateBitmap, /* pCreateBitmap */
   TTYDRV_DC_CreateDC,  /* pCreateDC */
   NULL,                /* pCreateDIBSection */
   NULL,                /* pCreateDIBSection16 */
   TTYDRV_DC_DeleteDC,  /* pDeleteDC */
-  NULL,                /* pDeleteObject */
+  TTYDRV_DC_DeleteObject, /* pDeleteObject */
   NULL,                /* pDeviceCapabilities */
-  NULL,                /* pEllipse */
+  TTYDRV_DC_Ellipse,   /* pEllipse */
   NULL,                /* pEndDoc */
   NULL,                /* pEndPage */
   NULL,                /* pEnumDeviceFonts */
   TTYDRV_DC_Escape,    /* pEscape */
   NULL,                /* pExcludeClipRect */
-  NULL,                /* pExcludeVisRect */
   NULL,                /* pExtDeviceMode */
-  NULL,                /* pExtFloodFill */
-  NULL,                /* pExtTextOut */
-  NULL,                /* pGetCharWidth */
-  NULL,                /* pGetPixel */
-  NULL,                /* pGetTextExtentPoint */
-  NULL,                /* pGetTextMetrics */
+  TTYDRV_DC_ExtFloodFill, /* pExtFloodFill */
+  TTYDRV_DC_ExtTextOut, /* pExtTextOut */
+  NULL,                /* pFillRgn */
+  NULL,                /* pFrameRgn */
+  TTYDRV_DC_GetCharWidth, /* pGetCharWidth */
+  TTYDRV_DC_GetPixel,  /* pGetPixel */
+  TTYDRV_DC_GetTextExtentPoint, /* pGetTextExtentPoint */
+  TTYDRV_DC_GetTextMetrics,  /* pGetTextMetrics */
   NULL,                /* pIntersectClipRect */
   NULL,                /* pIntersectVisRect */
-  NULL,                /* pLineTo */
-  NULL,                /* pLoadOEMResource */
-  NULL,                /* pMoveToEx */
+  TTYDRV_DC_LineTo,    /* pLineTo */
+  TTYDRV_DC_LoadOEMResource, /* pLoadOEMResource */
+  TTYDRV_DC_MoveToEx,  /* pMoveToEx */
   NULL,                /* pOffsetClipRgn */
   NULL,                /* pOffsetViewportOrg (optional) */
   NULL,                /* pOffsetWindowOrg (optional) */
-  NULL,                /* pPaintRgn */
-  NULL,                /* pPatBlt */
-  NULL,                /* pPie */
-  NULL,                /* pPolyPolygon */
-  NULL,                /* pPolyPolyline */
-  NULL,                /* pPolygon */
-  NULL,                /* pPolyline */
-  NULL,                /* pPolyBezier */
+  TTYDRV_DC_PaintRgn,  /* pPaintRgn */
+  TTYDRV_DC_PatBlt,    /* pPatBlt */
+  TTYDRV_DC_Pie,       /* pPie */
+  TTYDRV_DC_PolyPolygon, /* pPolyPolygon */
+  TTYDRV_DC_PolyPolyline, /* pPolyPolyline */
+  TTYDRV_DC_Polygon,   /* pPolygon */
+  TTYDRV_DC_Polyline,  /* pPolyline */
+  TTYDRV_DC_PolyBezier, /* pPolyBezier */
   NULL,                /* pRealizePalette */
-  NULL,                /* pRectangle */
+  TTYDRV_DC_Rectangle, /* pRectangle */
   NULL,                /* pRestoreDC */
-  NULL,                /* pRoundRect */
+  TTYDRV_DC_RoundRect, /* pRoundRect */
   NULL,                /* pSaveDC */
   NULL,                /* pScaleViewportExt (optional) */
   NULL,                /* pScaleWindowExt (optional) */
   NULL,                /* pSelectClipRgn */
-  NULL,                /* pSelectObject */
+  TTYDRV_DC_SelectObject, /* pSelectObject */
   NULL,                /* pSelectPalette */
-  NULL,                /* pSetBkColor */
+  TTYDRV_DC_SetBkColor, /* pSetBkColor */
   NULL,                /* pSetBkMode */
-  NULL,                /* pSetDeviceClipping */
+  TTYDRV_DC_SetDeviceClipping, /* pSetDeviceClipping */
   NULL,                /* pSetDIBitsToDevice */
   NULL,                /* pSetMapMode (optional) */
   NULL,                /* pSetMapperFlags */
-  NULL,                /* pSetPixel */
+  TTYDRV_DC_SetPixel,  /* pSetPixel */
   NULL,                /* pSetPolyFillMode */
   NULL,                /* pSetROP2 */
   NULL,                /* pSetRelAbs */
   NULL,                /* pSetStretchBltMode */
   NULL,                /* pSetTextAlign */
   NULL,                /* pSetTextCharacterExtra */
-  NULL,                /* pSetTextColor */
+  TTYDRV_DC_SetTextColor, /* pSetTextColor */
   NULL,                /* pSetTextJustification */
   NULL,                /* pSetViewportExt (optional) */
   NULL,                /* pSetViewportOrg (optional) */
@@ -90,7 +94,7 @@ static const DC_FUNCTIONS TTYDRV_DC_Driver =
   NULL,                /* pSetWindowOrg (optional) */
   NULL,                /* pStartDoc */
   NULL,                /* pStartPage */
-  NULL,                /* pStretchBlt */
+  TTYDRV_DC_StretchBlt, /* pStretchBlt */
   NULL                 /* pStretchDIBits */
 };
 
@@ -117,7 +121,7 @@ PALETTE_DRIVER TTYDRV_PALETTE_Driver =
 
 /* FIXME: Adapt to the TTY driver. Copied from the X11 driver */
 
-static DeviceCaps TTYDRV_DC_DevCaps = {
+DeviceCaps TTYDRV_DC_DevCaps = {
 /* version */		0, 
 /* technology */	DT_RASDISPLAY,
 /* size, resolution */	0, 0, 0, 0, 0, 
@@ -179,23 +183,60 @@ void TTYDRV_GDI_Finalize(void)
  *	     TTYDRV_DC_CreateDC
  */
 BOOL TTYDRV_DC_CreateDC(DC *dc, LPCSTR driver, LPCSTR device,
-			    LPCSTR output, const DEVMODEA *initData)
+			LPCSTR output, const DEVMODEA *initData)
 {
+  TTYDRV_PDEVICE *physDev;
+  BITMAPOBJ *bmp;
+
   FIXME("(%p, %s, %s, %s, %p): semistub\n",
     dc, debugstr_a(driver), debugstr_a(device), 
-    debugstr_a(output), initData
-  );
+    debugstr_a(output), initData);
 
-  dc->physDev = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
-			   sizeof(TTYDRV_PDEVICE) );
-  
+  dc->physDev = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+			  sizeof(TTYDRV_PDEVICE));  
   if(!dc->physDev) {
     ERR("Can't allocate physDev\n");
     return FALSE;
   }
-
-  dc->w.devCaps = &TTYDRV_DC_DevCaps;
+  physDev = (TTYDRV_PDEVICE *) dc->physDev;
   
+  dc->w.devCaps = &TTYDRV_DC_DevCaps;
+
+  if(dc->w.flags & DC_MEMORY){
+#ifdef HAVE_LIBCURSES
+    physDev->window = NULL;
+#endif /* defined(HAVE_LIBCURSES) */
+    physDev->cellWidth = 1;
+    physDev->cellHeight = 1;
+
+    TTYDRV_DC_CreateBitmap(dc->w.hBitmap);
+    bmp = (BITMAPOBJ *) GDI_GetObjPtr(dc->w.hBitmap, BITMAP_MAGIC);
+				   
+    dc->w.bitsPerPixel = bmp->bitmap.bmBitsPixel;
+    
+    dc->w.totalExtent.left   = 0;
+    dc->w.totalExtent.top    = 0;
+    dc->w.totalExtent.right  = bmp->bitmap.bmWidth;
+    dc->w.totalExtent.bottom = bmp->bitmap.bmHeight;
+    dc->w.hVisRgn            = CreateRectRgnIndirect( &dc->w.totalExtent );
+    
+    GDI_HEAP_UNLOCK( dc->w.hBitmap );
+  } else {
+#ifdef HAVE_LIBCURSES
+    physDev->window = TTYDRV_MONITOR_GetCursesRootWindow(&MONITOR_PrimaryMonitor);
+#endif /* defined(HAVE_LIBCURSES) */
+    physDev->cellWidth = TTYDRV_MONITOR_GetCellWidth(&MONITOR_PrimaryMonitor);
+    physDev->cellHeight = TTYDRV_MONITOR_GetCellHeight(&MONITOR_PrimaryMonitor);
+    
+    dc->w.bitsPerPixel = MONITOR_GetDepth(&MONITOR_PrimaryMonitor);
+    
+    dc->w.totalExtent.left   = 0;
+    dc->w.totalExtent.top    = 0;
+    dc->w.totalExtent.right  = MONITOR_GetWidth(&MONITOR_PrimaryMonitor);
+    dc->w.totalExtent.bottom = MONITOR_GetHeight(&MONITOR_PrimaryMonitor);
+    dc->w.hVisRgn            = CreateRectRgnIndirect( &dc->w.totalExtent );    
+  }
+
   return TRUE;
 }
 
diff --git a/graphics/ttydrv/objects.c b/graphics/ttydrv/objects.c
new file mode 100644
index 00000000000..421361a6fc9
--- /dev/null
+++ b/graphics/ttydrv/objects.c
@@ -0,0 +1,93 @@
+/*
+ * TTY DC objects
+ *
+ * Copyright 1999 Patrik Stridvall
+ */
+
+#include "bitmap.h"
+#include "brush.h"
+#include "dc.h"
+#include "font.h"
+#include "gdi.h"
+#include "pen.h"
+#include "ttydrv.h"
+#include "debugtools.h"
+
+DEFAULT_DEBUG_CHANNEL(ttydrv)
+
+/**********************************************************************/
+
+extern HBITMAP TTYDRV_DC_BITMAP_SelectObject(DC *dc, HBITMAP hbitmap, BITMAPOBJ *bitmap);
+extern HBRUSH TTYDRV_DC_BRUSH_SelectObject(DC *dc, HBRUSH hbrush, BRUSHOBJ *brush);
+extern HFONT TTYDRV_DC_FONT_SelectObject(DC* dc, HFONT hfont, FONTOBJ *font);
+extern HPEN TTYDRV_DC_PEN_SelectObject(DC *dc, HBRUSH hpen, PENOBJ *pen);
+
+extern BOOL TTYDRV_DC_BITMAP_DeleteObject(HBITMAP hbitmap, BITMAPOBJ *bitmap);
+
+/***********************************************************************
+ *		TTYDRV_DC_SelectObject
+ */
+HGDIOBJ TTYDRV_DC_SelectObject(DC *dc, HGDIOBJ handle)
+{
+  GDIOBJHDR *ptr = GDI_GetObjPtr(handle, MAGIC_DONTCARE);
+  HGDIOBJ result = NULL;
+
+  if(!ptr) return NULL;
+
+  switch(ptr->wMagic) 
+  {
+    case BITMAP_MAGIC:
+      result = TTYDRV_DC_BITMAP_SelectObject(dc, handle, (BITMAPOBJ *) ptr);
+      break;
+    case BRUSH_MAGIC:
+      result = TTYDRV_DC_BRUSH_SelectObject(dc, handle, (BRUSHOBJ *) ptr);
+      break;
+    case FONT_MAGIC:
+      result = TTYDRV_DC_FONT_SelectObject(dc, handle, (FONTOBJ *) ptr);	  
+      break;
+    case PEN_MAGIC:
+      result = TTYDRV_DC_PEN_SelectObject(dc, handle, (PENOBJ *) ptr);
+      break;
+    case REGION_MAGIC:
+      /* FIXME: Shouldn't be handled here */
+      result = (HGDIOBJ) SelectClipRgn(dc->hSelf, handle);
+      break;
+    default:
+      ERR("unknown magic (0x%04x)\n", ptr->wMagic);
+  }
+
+  GDI_HEAP_UNLOCK(handle);
+    
+  return result;
+}
+
+/***********************************************************************
+ *           TTYDRV_DC_DeleteObject
+ */
+BOOL TTYDRV_DC_DeleteObject(HGDIOBJ handle)
+{
+  GDIOBJHDR *ptr = GDI_GetObjPtr(handle, MAGIC_DONTCARE);
+  BOOL result;
+  
+  if(!ptr) return FALSE;
+     
+  switch(ptr->wMagic)
+  {
+    case BITMAP_MAGIC:
+      result = TTYDRV_DC_BITMAP_DeleteObject(handle, (BITMAPOBJ *) ptr);
+      break;
+    case BRUSH_MAGIC:
+    case FONT_MAGIC:
+    case PEN_MAGIC:
+    case REGION_MAGIC:
+      result = TRUE;
+      break;
+    default:
+      ERR("unknown magic (0x%04x)\n", ptr->wMagic);   
+      result = FALSE;
+  }
+
+  GDI_HEAP_UNLOCK(handle);
+
+  return result;
+}
diff --git a/graphics/ttydrv/oembitmap.c b/graphics/ttydrv/oembitmap.c
new file mode 100644
index 00000000000..f4f0611c35b
--- /dev/null
+++ b/graphics/ttydrv/oembitmap.c
@@ -0,0 +1,40 @@
+/*
+ * TTY DC OEM bitmap
+ *
+ * Copyright 1999 Patrik Stridvall
+ */
+
+#include "bitmap.h"
+#include "debugtools.h"
+#include "ttydrv.h"
+
+DEFAULT_DEBUG_CHANNEL(ttydrv)
+
+/**********************************************************************
+ *		TTYDRV_DC_LoadOEMResource
+ */
+HANDLE TTYDRV_DC_LoadOEMResource(WORD resid, WORD type)
+{
+  HBITMAP hbitmap;
+  BITMAPOBJ *bmpObjPtr;
+
+  FIXME("(%d, %d): semistub\n", resid, type);
+ 
+  if(!(hbitmap = GDI_AllocObject(sizeof(BITMAPOBJ), BITMAP_MAGIC)))
+    return (HANDLE) NULL;
+  
+  bmpObjPtr = (BITMAPOBJ *) GDI_HEAP_LOCK(hbitmap);
+  bmpObjPtr->size.cx = 0;
+  bmpObjPtr->size.cy = 0;
+  bmpObjPtr->bitmap.bmType       = 0;
+  bmpObjPtr->bitmap.bmWidth      = 0;
+  bmpObjPtr->bitmap.bmHeight     = 0;
+  bmpObjPtr->bitmap.bmWidthBytes = 0;
+  bmpObjPtr->bitmap.bmPlanes     = 0;
+  bmpObjPtr->bitmap.bmBitsPixel  = 0;
+  bmpObjPtr->bitmap.bmBits       = NULL;
+  bmpObjPtr->dib                 = NULL;
+  
+  GDI_HEAP_UNLOCK( hbitmap );
+  return hbitmap;
+}
diff --git a/graphics/ttydrv/palette.c b/graphics/ttydrv/palette.c
index c8bf91777b3..bff9309d6b5 100644
--- a/graphics/ttydrv/palette.c
+++ b/graphics/ttydrv/palette.c
@@ -4,23 +4,78 @@
  * Copyright 1999 Patrik Stridvall
  */
 
+#include "color.h"
+#include "debugtools.h"
 #include "palette.h"
 #include "ttydrv.h"
+#include "xmalloc.h"
 
-/**********************************************************************
+DEFAULT_DEBUG_CHANNEL(ttydrv)
+
+/**********************************************************************/
+
+extern DeviceCaps TTYDRV_DC_DevCaps;
+
+extern PALETTEENTRY *COLOR_sysPal;
+extern int COLOR_gapStart;
+extern int COLOR_gapEnd;
+extern int COLOR_gapFilled;
+extern int COLOR_max;
+
+extern const PALETTEENTRY COLOR_sysPalTemplate[NB_RESERVED_COLORS]; 
+
+/***********************************************************************
  *	     TTYDRV_PALETTE_Initialize
  */
 BOOL TTYDRV_PALETTE_Initialize(void)
 {
+  int i;
+
+  TRACE("(void)\n");
+
+  TTYDRV_DC_DevCaps.sizePalette = 256;
+
+  COLOR_sysPal = (PALETTEENTRY *) xmalloc(sizeof(PALETTEENTRY) * TTYDRV_DC_DevCaps.sizePalette);
+
+  for(i=0; i < TTYDRV_DC_DevCaps.sizePalette; i++ ) {
+    const PALETTEENTRY *src;
+    PALETTEENTRY *dst = &COLOR_sysPal[i];
+
+    if(i < NB_RESERVED_COLORS/2) {
+      src = &COLOR_sysPalTemplate[i];
+    } else if(i >= TTYDRV_DC_DevCaps.sizePalette - NB_RESERVED_COLORS/2) {
+      src = &COLOR_sysPalTemplate[NB_RESERVED_COLORS + i - TTYDRV_DC_DevCaps.sizePalette];
+    } else {
+      PALETTEENTRY pe = { 0, 0, 0, 0 };
+      src = &pe;
+    }
+
+    if((src->peRed + src->peGreen + src->peBlue) <= 0xB0) {
+      dst->peRed = 0;
+      dst->peGreen = 0;  
+      dst->peBlue = 0;
+      dst->peFlags = PC_SYS_USED;
+    } else {
+      dst->peRed = 255;  
+      dst->peGreen= 255;  
+      dst->peBlue = 255;
+      dst->peFlags = PC_SYS_USED;
+    }    
+  }
+
+  COLOR_gapStart = NB_RESERVED_COLORS/2;
+  COLOR_gapEnd = NB_RESERVED_COLORS/2;
+
   return TRUE;
 }
 
-/**********************************************************************
+/***********************************************************************
  *	     TTYDRV_PALETTE_Finalize
  *
  */
 void TTYDRV_PALETTE_Finalize(void)
 {
+  TRACE("(void)\n");
 }
 
 /***********************************************************************
@@ -29,6 +84,8 @@ void TTYDRV_PALETTE_Finalize(void)
 int TTYDRV_PALETTE_SetMapping(
   PALETTEOBJ *palPtr, UINT uStart, UINT uNum, BOOL mapOnly)
 {
+  FIXME("(%p, %u, %u, %d): stub\n", palPtr, uStart, uNum, mapOnly);
+
   return 0;
 }
 
@@ -37,6 +94,8 @@ int TTYDRV_PALETTE_SetMapping(
  */
 int TTYDRV_PALETTE_UpdateMapping(PALETTEOBJ *palPtr)
 {
+  FIXME("(%p): stub\n", palPtr);
+
   return 0;
 }
 
@@ -45,5 +104,7 @@ int TTYDRV_PALETTE_UpdateMapping(PALETTEOBJ *palPtr)
  */
 int TTYDRV_PALETTE_IsDark(int pixel)
 {
+  FIXME("(%d): stub\n", pixel);
+
   return 0;
 }
diff --git a/graphics/ttydrv/pen.c b/graphics/ttydrv/pen.c
new file mode 100644
index 00000000000..db09794e6e9
--- /dev/null
+++ b/graphics/ttydrv/pen.c
@@ -0,0 +1,22 @@
+/*
+ * TTY DC pen
+ *
+ * Copyright 1999 Patrik Stridvall
+ */
+
+#include "dc.h"
+#include "debugtools.h"
+#include "pen.h"
+#include "ttydrv.h"
+
+DEFAULT_DEBUG_CHANNEL(ttydrv)
+
+/***********************************************************************
+ *		TTYDRV_DC_PEN_SelectObject
+ */
+HPEN TTYDRV_DC_PEN_SelectObject(DC *dc, HBRUSH hpen, PENOBJ *pen)
+{
+  FIXME("(%p, 0x%08x, %p): stub\n", dc, hpen, pen);
+
+  return NULL;
+}
diff --git a/graphics/ttydrv/text.c b/graphics/ttydrv/text.c
new file mode 100644
index 00000000000..396bb0a28cb
--- /dev/null
+++ b/graphics/ttydrv/text.c
@@ -0,0 +1,58 @@
+/*
+ * TTY DC text
+ *
+ * Copyright 1999 Patrik Stridvall
+ */
+
+#include "config.h"
+
+#include "wine/wingdi16.h"
+#include "dc.h"
+#include "debugtools.h"
+#include "gdi.h"
+#include "ttydrv.h"
+
+DEFAULT_DEBUG_CHANNEL(ttydrv)
+
+/***********************************************************************
+ *		TTYDRV_DC_ExtTextOut
+ */
+BOOL TTYDRV_DC_ExtTextOut(DC *dc, INT x, INT y, UINT flags,
+			  const RECT *lpRect, LPCSTR str, UINT count,
+			  const INT *lpDx)
+{
+#ifdef HAVE_LIBCURSES
+  TTYDRV_PDEVICE *physDev = (TTYDRV_PDEVICE *) dc->physDev;
+  INT row, col;
+
+  FIXME("(%p, %d, %d, 0x%08x, %p, %s, %d, %p): semistub\n",
+	dc, x, y, flags, lpRect, debugstr_a(str), count, lpDx);
+
+  /* FIXME: Is this really correct? */
+  if(dc->w.textAlign & TA_UPDATECP) {
+    x = dc->w.CursPosX;
+    y = dc->w.CursPosY;
+  }
+
+  x = XLPTODP(dc, x);
+  y = YLPTODP(dc, y);
+  
+  row = (dc->w.DCOrgY + y) / physDev->cellHeight;
+  col = (dc->w.DCOrgX + x) / physDev->cellWidth;
+
+  mvwaddnstr(physDev->window, row, col, str, count);
+  wrefresh(physDev->window);
+
+  if(dc->w.textAlign & TA_UPDATECP) {
+    dc->w.CursPosX += count * physDev->cellWidth;
+    dc->w.CursPosY += count * physDev->cellHeight;
+  }
+
+  return TRUE;
+#else /* defined(HAVE_LIBCURSES) */
+  FIXME("(%p, %d, %d, 0x%08x, %p, %s, %d, %p): stub\n",
+	dc, x, y, flags, lpRect, debugstr_a(str), count, lpDx);
+
+  return TRUE;
+#endif /* defined(HAVE_LIBCURSES) */
+}
diff --git a/include/ttydrv.h b/include/ttydrv.h
index 8d390274e4f..7c9a4c9cd29 100644
--- a/include/ttydrv.h
+++ b/include/ttydrv.h
@@ -5,6 +5,15 @@
 #ifndef __WINE_TTYDRV_H
 #define __WINE_TTYDRV_H
 
+#include "config.h"
+
+#undef ERR
+#ifdef HAVE_NCURSES_H
+# include <ncurses.h>
+#elif defined(HAVE_CURSES_H)
+# include <curses.h>
+#endif
+
 #include "windef.h"
 #include "wingdi.h"
 #include "dinput.h"
@@ -40,12 +49,48 @@ extern INT TTYDRV_BITMAP_GetDIBits(struct tagBITMAPOBJ *bmp, struct tagDC *dc, U
 extern void TTYDRV_BITMAP_DeleteDIBSection(struct tagBITMAPOBJ *bmp);
 
 typedef struct {
-  int dummy;
+#ifdef HAVE_LIBCURSES
+  WINDOW *window;
+#endif /* defined(HAVE_LIBCURSES) */
+  int cellWidth;
+  int cellHeight;
 } TTYDRV_PDEVICE;
 
+extern BOOL TTYDRV_DC_Arc(struct tagDC *dc, INT left, INT top, INT right, INT bottom, INT xstart, INT ystart, INT xend, INT yend);
+extern BOOL TTYDRV_DC_CreateBitmap(HBITMAP hbitmap);
 extern BOOL TTYDRV_DC_CreateDC(struct tagDC *dc, LPCSTR driver, LPCSTR device, LPCSTR output, const DEVMODEA *initData);
 extern BOOL TTYDRV_DC_DeleteDC(struct tagDC *dc);
+extern BOOL TTYDRV_DC_DeleteObject(HGDIOBJ handle);
+extern BOOL TTYDRV_DC_BitBlt(struct tagDC *dcDst, INT xDst, INT yDst, INT width, INT height, struct tagDC *dcSrc, INT xSrc, INT ySrc, DWORD rop);
+extern BOOL TTYDRV_DC_Chord(struct tagDC *dc, INT left, INT top, INT right, INT bottom, INT xstart, INT ystart, INT xend, INT yend);
+extern BOOL TTYDRV_DC_Ellipse(struct tagDC *dc, INT left, INT top, INT right, INT bottom);
 extern INT TTYDRV_DC_Escape(struct tagDC *dc, INT nEscape, INT cbInput, SEGPTR lpInData, SEGPTR lpOutData);
+extern BOOL TTYDRV_DC_ExtFloodFill(struct tagDC *dc, INT x, INT y, COLORREF color, UINT fillType);
+extern BOOL TTYDRV_DC_ExtTextOut(struct tagDC *dc, INT x, INT y, UINT flags, const RECT *lpRect, LPCSTR str, UINT count, const INT *lpDx);
+extern BOOL TTYDRV_DC_GetCharWidth(struct tagDC *dc, UINT firstChar, UINT lastChar, LPINT buffer);
+extern COLORREF TTYDRV_DC_GetPixel(struct tagDC *dc, INT x, INT y);
+
+extern BOOL TTYDRV_DC_GetTextExtentPoint(struct tagDC *dc, LPCSTR str, INT count, LPSIZE size);
+extern BOOL TTYDRV_DC_GetTextMetrics(struct tagDC *dc, TEXTMETRICA *metrics);
+extern BOOL TTYDRV_DC_LineTo(struct tagDC *dc, INT x, INT y);
+extern HANDLE TTYDRV_DC_LoadOEMResource(WORD resid, WORD type);
+extern BOOL TTYDRV_DC_MoveToEx(struct tagDC *dc, INT x, INT y, LPPOINT pt);
+extern BOOL TTYDRV_DC_PaintRgn(struct tagDC *dc, HRGN hrgn);
+extern BOOL TTYDRV_DC_PatBlt(struct tagDC *dc, INT left, INT top, INT width, INT height, DWORD rop);
+extern BOOL TTYDRV_DC_Pie(struct tagDC *dc, INT left, INT top, INT right, INT bottom, INT xstart, INT ystart, INT xend, INT yend);
+extern BOOL TTYDRV_DC_PolyBezier(struct tagDC *dc, POINT start, const POINT* BezierPoints, DWORD count);
+extern BOOL TTYDRV_DC_Polygon(struct tagDC *dc, const POINT* pt, INT count);
+extern BOOL TTYDRV_DC_Polyline(struct tagDC *dc, const POINT* pt, INT count);
+extern BOOL TTYDRV_DC_PolyPolygon(struct tagDC *dc, const POINT* pt, const INT* counts, UINT polygons);
+extern BOOL TTYDRV_DC_PolyPolyline(struct tagDC *dc, const POINT* pt, const DWORD* counts, DWORD polylines);
+extern BOOL TTYDRV_DC_Rectangle(struct tagDC *dc, INT left, INT top, INT right, INT bottom);
+extern BOOL TTYDRV_DC_RoundRect(struct tagDC *dc, INT left, INT top, INT right, INT bottom, INT ell_width, INT ell_height);
+extern void TTYDRV_DC_SetDeviceClipping(struct tagDC *dc);
+extern HGDIOBJ TTYDRV_DC_SelectObject(struct tagDC *dc, HGDIOBJ handle);
+extern COLORREF TTYDRV_DC_SetBkColor(struct tagDC *dc, COLORREF color);
+extern COLORREF TTYDRV_DC_SetPixel(struct tagDC *dc, INT x, INT y, COLORREF color);
+extern COLORREF TTYDRV_DC_SetTextColor(struct tagDC *dc, COLORREF color);
+extern BOOL TTYDRV_DC_StretchBlt(struct tagDC *dcDst, INT xDst, INT yDst, INT widthDst, INT heightDst, struct tagDC *dcSrc, INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, DWORD rop);
 
 /* TTY GDI palette driver */
 
@@ -86,6 +131,10 @@ extern void TTYDRV_CLIPBOARD_ResetOwner(struct tagWND *pWnd, BOOL bFooBar);
 
 extern struct tagDESKTOP_DRIVER TTYDRV_DESKTOP_Driver;
 
+#ifdef HAVE_LIBCURSES
+extern WINDOW *TTYDRV_DESKTOP_GetCursesRootWindow(struct tagDESKTOP *pDesktop);
+#endif /* defined(HAVE_LIBCURSES) */
+
 extern void TTYDRV_DESKTOP_Initialize(struct tagDESKTOP *pDesktop);
 extern void TTYDRV_DESKTOP_Finalize(struct tagDESKTOP *pDesktop);
 extern int TTYDRV_DESKTOP_GetScreenWidth(struct tagDESKTOP *pDesktop);
@@ -120,7 +169,12 @@ extern BOOL TTYDRV_KEYBOARD_GetDIData(BYTE *keystate, DWORD dodsize, LPDIDEVICEO
 
 extern struct tagMONITOR_DRIVER TTYDRV_MONITOR_Driver;
 
-typedef struct _TTYDRV_MONITOR_DATA {
+typedef struct tagTTYDRV_MONITOR_DATA {
+#ifdef HAVE_LIBCURSES
+  WINDOW  *rootWindow;
+#endif /* defined(HAVE_LIBCURSES) */
+  int      cellWidth;
+  int      cellHeight;
   int      width;
   int      height;
   int      depth;
@@ -128,6 +182,13 @@ typedef struct _TTYDRV_MONITOR_DATA {
 
 struct tagMONITOR;
 
+#ifdef HAVE_LIBCURSES
+extern WINDOW *TTYDRV_MONITOR_GetCursesRootWindow(struct tagMONITOR *pMonitor);
+#endif /* defined(HAVE_LIBCURSES) */
+
+extern INT TTYDRV_MONITOR_GetCellWidth(struct tagMONITOR *pMonitor);
+extern INT TTYDRV_MONITOR_GetCellHeight(struct tagMONITOR *pMonitor);
+
 extern void TTYDRV_MONITOR_Initialize(struct tagMONITOR *pMonitor);
 extern void  TTYDRV_MONITOR_Finalize(struct tagMONITOR *pMonitor);
 extern BOOL TTYDRV_MONITOR_IsSingleWindow(struct tagMONITOR *pMonitor);
@@ -152,6 +213,19 @@ extern BOOL TTYDRV_MOUSE_EnableWarpPointer(BOOL bEnable);
 
 extern struct tagWND_DRIVER TTYDRV_WND_Driver;
 
+typedef struct tagTTYDRV_WND_DATA {
+#ifdef HAVE_LIBCURSES
+  WINDOW *window;
+#else /* defined(HAVE_LIBCURSES) */
+  int dummy; /* FIXME: Remove later */
+#endif /* defined(HAVE_LIBCURSES) */
+} TTYDRV_WND_DATA;
+
+#ifdef HAVE_LIBCURSES
+WINDOW *TTYDRV_WND_GetCursesWindow(struct tagWND *wndPtr);
+WINDOW *TTYDRV_WND_GetCursesRootWindow(struct tagWND *wndPtr);
+#endif /* defined(HAVE_LIBCURSES) */
+
 extern void TTYDRV_WND_Initialize(struct tagWND *wndPtr);
 extern void TTYDRV_WND_Finalize(struct tagWND *wndPtr);
 extern BOOL TTYDRV_WND_CreateDesktopWindow(struct tagWND *wndPtr, struct tagCLASS *classPtr, BOOL bUnicode);
diff --git a/windows/ttydrv/desktop.c b/windows/ttydrv/desktop.c
index d6c7bee4508..3e1334b15aa 100644
--- a/windows/ttydrv/desktop.c
+++ b/windows/ttydrv/desktop.c
@@ -5,15 +5,35 @@
  *
  */
 
+#include "config.h"
+
+#include "debugtools.h"
 #include "desktop.h"
 #include "monitor.h"
 #include "ttydrv.h"
 
+DEFAULT_DEBUG_CHANNEL(ttydrv)
+
+/***********************************************************************
+ *              TTYDRV_DESKTOP_GetCursesRootWindow
+ *
+ * Return the Curses root window associated to the desktop.
+ */
+#ifdef HAVE_LIBCURSES
+WINDOW *TTYDRV_DESKTOP_GetCursesRootWindow(DESKTOP *pDesktop)
+{
+  return TTYDRV_MONITOR_GetCursesRootWindow(pDesktop->pPrimaryMonitor);
+}
+#endif /* defined(HAVE_LIBCURSES) */
+
 /***********************************************************************
  *              TTYDRV_DESKTOP_Initialize
  */
 void TTYDRV_DESKTOP_Initialize(DESKTOP *pDesktop)
 {
+  TRACE("(%p): stub\n", pDesktop);
+
+  pDesktop->pPrimaryMonitor = &MONITOR_PrimaryMonitor;
 }
 
 /***********************************************************************
@@ -21,6 +41,7 @@ void TTYDRV_DESKTOP_Initialize(DESKTOP *pDesktop)
  */
 void TTYDRV_DESKTOP_Finalize(DESKTOP *pDesktop)
 {
+  TRACE("(%p): stub\n", pDesktop);
 }
 
 /***********************************************************************
diff --git a/windows/ttydrv/main.c b/windows/ttydrv/main.c
index b3985852742..f3ccb61d7bc 100644
--- a/windows/ttydrv/main.c
+++ b/windows/ttydrv/main.c
@@ -5,6 +5,8 @@
  *
  */
 
+#include "config.h"
+
 #include "clipboard.h"
 #include "desktop.h"
 #include "message.h"
@@ -35,6 +37,9 @@ BOOL TTYDRV_USER_Initialize(void)
  */
 void TTYDRV_USER_Finalize(void)
 {
+#ifdef HAVE_LIBCURSES
+  endwin();
+#endif /* defined(HAVE_LIBCURSES) */
 }
 
 /**************************************************************************
diff --git a/windows/ttydrv/monitor.c b/windows/ttydrv/monitor.c
index bf5297c449d..07cf236e67d 100644
--- a/windows/ttydrv/monitor.c
+++ b/windows/ttydrv/monitor.c
@@ -5,11 +5,53 @@
  *
  */
 
+#include "config.h"
+
+#include "debugtools.h"
 #include "heap.h"
 #include "monitor.h"
 #include "windef.h"
 #include "ttydrv.h"
 
+DEFAULT_DEBUG_CHANNEL(ttydrv)
+
+/***********************************************************************
+ *              TTYDRV_MONITOR_GetCursesRootWindow
+ *
+ * Return the Curses root window associated to the MONITOR.
+ */
+#ifdef HAVE_LIBCURSES
+WINDOW *TTYDRV_MONITOR_GetCursesRootWindow(MONITOR *pMonitor)
+{
+  TTYDRV_MONITOR_DATA *pTTYMonitor =
+    (TTYDRV_MONITOR_DATA *) pMonitor->pDriverData;
+
+  return pTTYMonitor->rootWindow;
+}
+#endif /* defined(HAVE_LIBCURSES) */
+
+/***********************************************************************
+ *              TTYDRV_MONITOR_GetCellWidth
+ */
+INT TTYDRV_MONITOR_GetCellWidth(MONITOR *pMonitor)
+{
+  TTYDRV_MONITOR_DATA *pTTYMonitor =
+    (TTYDRV_MONITOR_DATA *) pMonitor->pDriverData;
+
+  return pTTYMonitor->cellWidth;
+}
+
+/***********************************************************************
+ *              TTYDRV_MONITOR_GetCellHeight
+ */
+INT TTYDRV_MONITOR_GetCellHeight(MONITOR *pMonitor)
+{
+  TTYDRV_MONITOR_DATA *pTTYMonitor =
+    (TTYDRV_MONITOR_DATA *) pMonitor->pDriverData;
+
+  return pTTYMonitor->cellHeight;
+}
+
 /***********************************************************************
  *              TTYDRV_MONITOR_Initialize
  */
@@ -17,12 +59,27 @@ void TTYDRV_MONITOR_Initialize(MONITOR *pMonitor)
 {
   TTYDRV_MONITOR_DATA *pTTYMonitor = (TTYDRV_MONITOR_DATA *) 
     HeapAlloc(SystemHeap, 0, sizeof(TTYDRV_MONITOR_DATA));
+  int rows, cols;
 
   pMonitor->pDriverData = pTTYMonitor;
 
-  pTTYMonitor->width  = 640; /* FIXME: Screen width in pixels */
-  pTTYMonitor->height = 480; /* FIXME: Screen height in pixels */
-  pTTYMonitor->depth  = 1;   /* FIXME: Screen depth */
+  pTTYMonitor->cellWidth = 8;
+  pTTYMonitor->cellHeight = 8;
+
+#ifdef HAVE_LIBCURSES
+  pTTYMonitor->rootWindow = initscr();
+  werase(pTTYMonitor->rootWindow);
+  wrefresh(pTTYMonitor->rootWindow);
+
+  getmaxyx(pTTYMonitor->rootWindow, rows, cols);
+#else /* defined(HAVE_LIBCURSES) */
+  rows = 60; /* FIXME: Hardcoded */
+  cols = 80; /* FIXME: Hardcoded */
+#endif /* defined(HAVE_LIBCURSES) */
+
+  pTTYMonitor->width  = pTTYMonitor->cellWidth*cols;
+  pTTYMonitor->height = pTTYMonitor->cellWidth*rows;
+  pTTYMonitor->depth  = 1;
 }
 
 /***********************************************************************
@@ -97,6 +154,7 @@ BOOL TTYDRV_MONITOR_GetScreenSaveActive(MONITOR *pMonitor)
  */
 void TTYDRV_MONITOR_SetScreenSaveActive(MONITOR *pMonitor, BOOL bActivate)
 {
+  FIXME("(%p, %d): stub\n", pMonitor, bActivate);
 }
 
 /***********************************************************************
@@ -117,4 +175,5 @@ int TTYDRV_MONITOR_GetScreenSaveTimeout(MONITOR *pMonitor)
 void TTYDRV_MONITOR_SetScreenSaveTimeout(
   MONITOR *pMonitor, int nTimeout)
 {
+  FIXME("(%p, %d): stub\n", pMonitor, nTimeout);
 }
diff --git a/windows/ttydrv/wnd.c b/windows/ttydrv/wnd.c
index e4880372a72..4d662bf6b0e 100644
--- a/windows/ttydrv/wnd.c
+++ b/windows/ttydrv/wnd.c
@@ -4,16 +4,59 @@
  * Copyright 1998,1999 Patrik Stridvall
  */
 
+#include "config.h"
+
 #include "class.h"
 #include "dc.h"
+#include "heap.h"
 #include "ttydrv.h"
 #include "win.h"
+#include "debugtools.h"
+
+DEFAULT_DEBUG_CHANNEL(ttydrv)
+
+/***********************************************************************
+ *		TTYDRV_WND_GetCursesWindow
+ *
+ * Return the Curses window associated to a window.
+ */
+#ifdef HAVE_LIBCURSES
+WINDOW *TTYDRV_WND_GetCursesWindow(WND *wndPtr)
+{
+    return wndPtr && wndPtr->pDriverData ? 
+      ((TTYDRV_WND_DATA *) wndPtr->pDriverData)->window : 0;
+}
+#endif /* defined(HAVE_LIBCURSES) */
+
+/***********************************************************************
+ *              TTYDRV_WND_GetCursesRootWindow
+ *
+ * Return the Curses root window of the Curses window associated 
+ * to a window.
+ */
+#ifdef HAVE_LIBCURSES
+WINDOW *TTYDRV_WND_GetCursesRootWindow(WND *wndPtr)
+{
+  while(wndPtr->parent) wndPtr = wndPtr->parent;
+  return TTYDRV_DESKTOP_GetCursesRootWindow((struct tagDESKTOP *) wndPtr->wExtra);
+}
+#endif /* defined(HAVE_LIBCURSES) */
 
 /**********************************************************************
  *		TTYDRV_WND_Initialize
  */
 void TTYDRV_WND_Initialize(WND *wndPtr)
 {
+  TTYDRV_WND_DATA *pWndDriverData = 
+    (TTYDRV_WND_DATA *) HeapAlloc(SystemHeap, 0, sizeof(TTYDRV_WND_DATA));
+
+  TRACE("(%p)\n", wndPtr);
+
+  wndPtr->pDriverData = (void *) pWndDriverData;
+
+#ifdef HAVE_LIBCURSES
+  pWndDriverData->window = NULL;
+#endif /* defined(HAVE_LIBCURSES) */
 }
 
 /**********************************************************************
@@ -21,6 +64,24 @@ void TTYDRV_WND_Initialize(WND *wndPtr)
  */
 void TTYDRV_WND_Finalize(WND *wndPtr)
 {
+  TTYDRV_WND_DATA *pWndDriverData =
+    (TTYDRV_WND_DATA *) wndPtr->pDriverData;
+
+  TRACE("(%p)\n", wndPtr);
+
+  if(!pWndDriverData) {
+    ERR("WND already destroyed\n");
+    return;
+  }
+
+#ifdef HAVE_LIBCURSES
+  if(pWndDriverData->window) {
+    ERR("WND destroyed without destroying the associated Curses Windows");
+  }
+#endif /* defined(HAVE_LIBCURSES) */
+
+  HeapFree(SystemHeap, 0, pWndDriverData);
+  wndPtr->pDriverData = NULL;
 }
 
 /**********************************************************************
@@ -28,7 +89,18 @@ void TTYDRV_WND_Finalize(WND *wndPtr)
  */
 BOOL TTYDRV_WND_CreateDesktopWindow(WND *wndPtr, CLASS *classPtr, BOOL bUnicode)
 {
-  return FALSE;
+  TTYDRV_WND_DATA *pWndDriverData =
+    (TTYDRV_WND_DATA *) wndPtr->pDriverData;
+
+  TRACE("(%p, %p, %d)\n", wndPtr, classPtr, bUnicode);
+
+  if(!pWndDriverData) { ERR("WND never initialized\n"); return FALSE; }
+
+#ifdef HAVE_LIBCURSES
+  pWndDriverData->window = TTYDRV_WND_GetCursesRootWindow(wndPtr);
+#endif /* defined(HAVE_LIBCURSES) */
+
+  return TRUE;
 }
 
 /**********************************************************************
@@ -36,7 +108,29 @@ BOOL TTYDRV_WND_CreateDesktopWindow(WND *wndPtr, CLASS *classPtr, BOOL bUnicode)
  */
 BOOL TTYDRV_WND_CreateWindow(WND *wndPtr, CLASS *classPtr, CREATESTRUCTA *cs, BOOL bUnicode)
 {
-  return FALSE;
+#ifdef HAVE_LIBCURSES
+  WINDOW *window, *rootWindow;
+  INT cellWidth=8, cellHeight=8; /* FIXME: Hardcoded */
+
+  TRACE("(%p, %p, %p, %d)\n", wndPtr, classPtr, cs, bUnicode);
+
+  /* Only create top-level windows */
+  if(cs->style & WS_CHILD)
+    return TRUE;
+
+  rootWindow = TTYDRV_WND_GetCursesRootWindow(wndPtr);
+
+  window = subwin(rootWindow, cs->cy/cellHeight, cs->cx/cellWidth,
+		  cs->y/cellHeight, cs->x/cellWidth);
+  werase(window);
+  wrefresh(window);
+		  
+  return TRUE;
+#else /* defined(HAVE_LIBCURSES) */
+  FIXME("(%p, %p, %p, %d): stub\n", wndPtr, classPtr, cs, bUnicode);
+
+  return TRUE;
+#endif /* defined(HAVE_LIBCURSES) */
 }
 
 /***********************************************************************
@@ -44,7 +138,22 @@ BOOL TTYDRV_WND_CreateWindow(WND *wndPtr, CLASS *classPtr, CREATESTRUCTA *cs, BO
  */
 BOOL TTYDRV_WND_DestroyWindow(WND *wndPtr)
 {
-  return FALSE;
+#ifdef HAVE_LIBCURSES
+  WINDOW *window;
+
+  TRACE("(%p)\n", wndPtr);
+
+  window = TTYDRV_WND_GetCursesWindow(wndPtr);
+  if(window && window != TTYDRV_WND_GetCursesRootWindow(wndPtr)) {
+    delwin(window);
+  }
+
+  return TRUE;
+#else /* defined(HAVE_LIBCURSES) */
+  FIXME("(%p): stub\n", wndPtr);
+
+  return TRUE;
+#endif /* defined(HAVE_LIBCURSES) */
 }
 
 /*****************************************************************
@@ -52,6 +161,8 @@ BOOL TTYDRV_WND_DestroyWindow(WND *wndPtr)
  */
 WND *TTYDRV_WND_SetParent(WND *wndPtr, WND *pWndParent)
 {
+  FIXME("(%p, %p): stub\n", wndPtr, pWndParent);
+
   return NULL;
 }
 
@@ -60,20 +171,23 @@ WND *TTYDRV_WND_SetParent(WND *wndPtr, WND *pWndParent)
  */
 void TTYDRV_WND_ForceWindowRaise(WND *wndPtr)
 {
+  FIXME("(%p): stub\n", wndPtr);
 }
 
 /***********************************************************************
- *           WINPOS_SetXWindowPos
+ *           TTYDRV_WINPOS_SetWindowPos
  */
 void TTYDRV_WND_SetWindowPos(WND *wndPtr, const WINDOWPOS *winpos, BOOL bSMC_SETXPOS)
 {
+  FIXME("(%p, %p, %d): stub\n", wndPtr, winpos, bSMC_SETXPOS);
 }
 
 /*****************************************************************
  *		TTYDRV_WND_SetText
  */
 void TTYDRV_WND_SetText(WND *wndPtr, LPCSTR text)
-{   
+{
+  FIXME("(%p, %s): stub\n", wndPtr, debugstr_a(text));
 }
 
 /*****************************************************************
@@ -81,6 +195,7 @@ void TTYDRV_WND_SetText(WND *wndPtr, LPCSTR text)
  */
 void TTYDRV_WND_SetFocus(WND *wndPtr)
 {
+  FIXME("(%p): stub\n", wndPtr);
 }
 
 /*****************************************************************
@@ -88,6 +203,7 @@ void TTYDRV_WND_SetFocus(WND *wndPtr)
  */
 void TTYDRV_WND_PreSizeMove(WND *wndPtr)
 {
+  FIXME("(%p): stub\n", wndPtr);
 }
 
 /*****************************************************************
@@ -95,9 +211,9 @@ void TTYDRV_WND_PreSizeMove(WND *wndPtr)
  */
 void TTYDRV_WND_PostSizeMove(WND *wndPtr)
 {
+  FIXME("(%p): stub\n", wndPtr);
 }
 
-
 /*****************************************************************
  *		 TTYDRV_WND_ScrollWindow
  */
@@ -105,6 +221,8 @@ void TTYDRV_WND_ScrollWindow(
   WND *wndPtr, DC *dcPtr, INT dx, INT dy, 
   const RECT *clipRect, BOOL bUpdate)
 {
+  FIXME("(%p, %p, %d, %d, %p, %d): stub\n", 
+	wndPtr, dcPtr, dx, dy, clipRect, bUpdate);
 }
 
 /***********************************************************************
@@ -112,6 +230,21 @@ void TTYDRV_WND_ScrollWindow(
  */
 void TTYDRV_WND_SetDrawable(WND *wndPtr, DC *dc, WORD flags, BOOL bSetClipOrigin)
 {
+  FIXME("(%p, %p, %d, %d): semistub\n", wndPtr, dc, flags, bSetClipOrigin);
+
+  if (!wndPtr)  {
+    /* Get a DC for the whole screen */
+    dc->w.DCOrgX = 0;
+    dc->w.DCOrgY = 0;
+  } else {
+    if (flags & DCX_WINDOW) {
+      dc->w.DCOrgX = wndPtr->rectWindow.left;
+      dc->w.DCOrgY = wndPtr->rectWindow.top;
+    } else {
+      dc->w.DCOrgX = wndPtr->rectClient.left;
+      dc->w.DCOrgY = wndPtr->rectClient.top;
+    }
+  }
 }
 
 /***********************************************************************
@@ -119,7 +252,9 @@ void TTYDRV_WND_SetDrawable(WND *wndPtr, DC *dc, WORD flags, BOOL bSetClipOrigin
  */
 BOOL TTYDRV_WND_SetHostAttr(WND *wndPtr, INT attr, INT value)
 {
-    return FALSE;
+  FIXME("(%p): stub\n", wndPtr);
+
+  return TRUE;
 }
 
 /***********************************************************************
@@ -127,5 +262,7 @@ BOOL TTYDRV_WND_SetHostAttr(WND *wndPtr, INT attr, INT value)
  */
 BOOL TTYDRV_WND_IsSelfClipping(WND *wndPtr)
 {
+  FIXME("(%p): semistub\n", wndPtr);
+
   return FALSE;
 }
-- 
GitLab