#ifdef WINCIT
#include "ctdl.h"

#define NUMCOLUMNS	80
#define NUMLINES	1000

// this is the memory buffer for the screen
static char huge *screenBuffer;

// top, left is the location of the tl corner of the screen from 0 to NUM...
// start is the line with the oldest stuff in screenBuffer
// cursorCol and cursorRow are where the text cursor is, relative to top, left
static int top, left, start, cursorCol, cursorRow;

void output(int Column, int Row, LPSTR str)
	{
	if (!screenBuffer)
		{
		screenBuffer = getMemG(NUMCOLUMNS * NUMLINES * 2, 1);
		}

	if (screenBuffer)
		{
		LPSTR ptr;
		RECT r;
//		HDC hdc;

//		if (haveFocus)
//			{
//			HideCaret(hwndMain);
//			}
//
//		hdc = GetDC(hwndMain);
//
//		TextOut(hdc, cxChar * (Column - left + 1),
//				cyChar * (1 + Row) - topBorder,
//				str, strlen(str));
//
//		ReleaseDC(hwndMain, hdc);
//
//		if (haveFocus)
//			{
//			ShowCaret(hwndMain);
//			}

		r.top = cyChar * (1 + Row) - topBorder;
		r.left = cxChar * (Column - left + 1);
		r.right = r.left + strlen(str) * cxChar;
		r.bottom = r.top + cyChar;
		InvalidateRect(hwndMain, &r, TRUE);

		if (memDC)
			{
			TextOut(memDC, cxChar * (Column - left + 1),
					cyChar * (1 + Row) - topBorder,
					str, strlen(str));
			}

		for (ptr = str; *ptr; ptr++)
			{
			long offset = (((long) left + (long) Column++) +
					(((long) start + (long) top + (long) Row) % NUMLINES) *
					NUMCOLUMNS) * (long) 2;

			screenBuffer[offset++] = *ptr;
			screenBuffer[offset] = TI()OC.ansiattr;
			}

		}
	}

// this ignores colors right now. i'll worry about that later.
void updateText(RECT r, HDC hdc)
	{
	if (screenBuffer)
		{
		int lineCur, lineStart, lineEnd, colStart, colEnd;
		NPSTR lineBuffer;

		r.top = max(r.top, topBorder);
		r.bottom = max(r.bottom, topBorder);
		r.left = max(r.left, cxChar);
		r.right = max(r.right, cxChar);
		
		lineStart = (r.top - topBorder) / cyChar;
		lineEnd = (r.bottom - topBorder + cyChar - 1) / cyChar - 1;
		colStart = (r.left - cxChar) / cxChar;
		colEnd = (r.right - cxChar) / cxChar;

		lineBuffer = (NPSTR) LocalAlloc(LPTR, colEnd - colStart + 2);

		for (lineCur = lineStart; lineCur <= lineEnd; lineCur++)
			{
			int col;

			for (col = left + colStart; col <= left + colEnd; col++)
				{
				long offset = ((long) col + (((long) start + (long) top + (long) lineCur) % NUMLINES) * NUMCOLUMNS) * (long) 2;
				char ch = screenBuffer[offset];
				
				if (ch < 32)
					{
					ch = 32;
					}

				lineBuffer[col - left - colStart] = ch;
				}

			TextOut(hdc, cxChar * (colStart - left + 1),
					cyChar * (1 + lineCur) - topBorder,
					lineBuffer, strlen(lineBuffer));

			if (memDC)
				{
				TextOut(memDC, cxChar * (colStart - left + 1),
						cyChar * (1 + lineCur) - topBorder,
						lineBuffer, strlen(lineBuffer));
				}
			}

		LocalFree((LOCALHANDLE) lineBuffer);
		}
	}

// petzold, pp 621-622
void DrawBitmap(HDC hdc, HBITMAP hBitmap, short xStart, short yStart)
	{
	BITMAP bm;
	HDC hdcMem;
	POINT ptSize, ptOrg;

	hdcMem = CreateCompatibleDC(hdc);
	SelectObject(hdcMem, hBitmap);
	SetMapMode(hdcMem, GetMapMode(hdc));

	GetObject(hBitmap, sizeof(BITMAP), (LPSTR) &bm);

	ptSize.x = bm.bmWidth;
	ptSize.y = bm.bmHeight;
	DPtoLP(hdc, &ptSize, 1);

	ptOrg.x = 0;
	ptOrg.y = 0;
	DPtoLP(hdcMem, &ptOrg, 1);

	BitBlt(hdc, xStart, yStart, ptSize.x, ptSize.y, hdcMem, ptOrg.x, ptOrg.y,
			SRCCOPY);

	DeleteDC(hdcMem);
	}

void readpos(uchar *row, uchar *column)
	{
	*row = cursorRow;
	*column = cursorCol;
	}

void position(uchar row, uchar column)
	{
	cursorRow = row;
	cursorCol = column;

	if (haveFocus)
		{
		SetCaretPos(cursorCol * cxChar + cxChar,
				cursorRow * cyChar + topBorder);
		}
	}

void incTop(int attr)
	{
	top++;
	if (top >= NUMLINES)
		{
		int i;
		uchar huge *c;

		for (c = (uchar huge *) screenBuffer +
				((long) start * NUMCOLUMNS) * 2, i = 0; i < NUMCOLUMNS;
				c += 2, i++)
			{
			*c = ' ';
			*(c + 1) = attr;
			}

		start = (start + 1) % NUMLINES;
		top--;
		}
	}

// we ignore the row - it is used to not scroll the status line in the DOS
// version. our status is another window so we don't have to worry about it
// at all.
void scroll(uchar row, uchar howmany, uchar attr)
	{
	for (; howmany; howmany--)
		{
		incTop(attr);
		}

	resetTextWindow(attr, FALSE);

	if (memDC)
		{
		// do the scrolly bltblt thing
		RECT r;
		HDC hdc;

		if (haveFocus)
			{
			HideCaret(hwndMain);
			}

		hdc = GetDC(hwndMain);

		// move it in the memDC
		BitBlt(memDC, cxChar, topBorder + 1, cxClient - cxChar,
				cyClient - cyChar - topBorder + 1, memDC, cxChar,
				topBorder + cyChar + 1, SRCCOPY);

		// and copy the results to the display
		BitBlt(hdc, cxChar, topBorder, cxClient - cxChar,
				cyClient - cyChar - topBorder + 1, memDC, cxChar, topBorder,
				SRCCOPY);

		// now just blank out the last line...
		r.top = (cyChar * scrollpos) + topBorder;
		r.bottom = r.top + cyChar + 1;
		r.left = cxChar;
		r.right = cxClient;

		FillRect(hdc, &r, GetStockObject(WHITE_BRUSH));
		FillRect(memDC, &r, GetStockObject(WHITE_BRUSH));

		ReleaseDC(hwndMain, hdc);

		if (haveFocus)
			{
			ShowCaret(hwndMain);
			}
		}
	else
		{
		// cheese out and redraw it all
		InvalidateRect(hwndMain, NULL, TRUE);
		}
	}

// call this whenever you do any size/scroll stuff with it after updating
// the global variables
void resetTextWindow(int attr, Bool resize)
	{
	int newLins, newCols, wow;

	// this stuff handles resizing the window down (we ignore upsizing and
	// just let there be ugly whitespace. it's the best way, i think.)
	wow = max(cyClient - topBorder, 0);
	newLins = wow / cyChar;

	wow = max(cxClient - cxChar, 0);
	newCols = wow / cxChar;

	if (resize)
		{
		left = 0;

		while (cursorRow > newLins - 1)
			{
			incTop(attr);
			cursorRow--;
			}

		while (cursorCol > newCols)
			{
			left++;
			cursorCol--;
			}

		if (haveFocus)
			{
			SetCaretPos(cursorCol * cxChar + cxChar,
					cursorRow * cyChar + topBorder);
			}

		// and tell the rest of cit how big we are
		scrollpos = newLins - 1;

		// and redraw the thing
		InvalidateRect(hwndMain, NULL, TRUE);
		}

	// now we make sure that we have enough screen space left...
	// this is really silly looking, but I don't want to think of a cleaner
	// way to do it right now. maybe later.
	for (wow = 1; wow < newLins; wow++)
		{
		if (top + wow >= NUMLINES)
			{
			int i;
			uchar huge *c;

			for (c = (uchar huge *) screenBuffer +
					((long) start * NUMCOLUMNS) * 2, i = 0; i < NUMCOLUMNS;
					c += 2, i++)
				{
				*c = ' ';
				*(c + 1) = attr;
				}

			start = (start + 1) % NUMLINES;
			top--;
			}
		}
	}

int ansi(char wow)
	{
	return (FALSE);
	}

Bool winchar(char ch, uchar attr, Bool phys)
	{
	char wow[2];

	wow[0] = ch;
	wow[1] = 0;
	TI()OC.ansiattr = attr;

	output(cursorCol, cursorRow, wow);

	cursorCol++;
	if (haveFocus)
		{
		SetCaretPos(cursorCol * cxChar + cxChar,
				cursorRow * cyChar + topBorder);
		}

	if (cursorCol == NUMCOLUMNS)
		{
		return (TRUE);
		}
	else
		{
		return (FALSE);
		}
	}

void winstring(uint row, char *str, uchar attr, Bool phys)
	{
	TI()OC.ansiattr = attr;
	output(0, row, str);
	cursorRow = row;
	cursorCol = strlen(str);

	if (haveFocus)
		{
		SetCaretPos(cursorCol * cxChar + cxChar,
				cursorRow * cyChar + topBorder);
		}
	}

void setscreen(void)
	{
	charattr = winchar;
	stringattr = winstring;
	}
#endif