// assumes tabs aren't going to get reset yet
#define STRICT 
#include <windows.h>
#include "header.h"
#include <richedit.h>
typedef struct {
	int stop ;
	int ofs ;
} EDITDATA ;
#define LEFTMARGIN 5
extern HINSTANCE hInstance ;
static WNDPROC oldproc ;
static HFONT hNormalFont ;
static int wndoffs ;
HBRUSH backgroundBrush ;

char *GetEditData(HWND) ;

static void doTextOut(HDC dc,int row,int charofs, char *buf,int chars, int stop)
{
	char hold[1024] ;
	int i = 0,tab=0,j=0 ;
	buf[chars]= 0 ;
	while (buf[j])
		if (buf[j] == '\t') {
				int nextcol = (i + stop)/stop*stop;
				while (i < nextcol)
					hold[i++] = ' ' ;
				j++ ;
		} else
			hold[i++] = buf[j++ ] ;
	hold[i] = 0 ;
	if (charofs < i)
		TextOut(dc,LEFTMARGIN,row,hold+charofs,i-charofs) ;
}
static int linetobuf(char *data, int *index,char *buf)
{
	int rv = 0;
	while (data[*index] && (data[*index] >= ' ' || data[*index] == '\t'))
		buf[rv++] = data[(*index)++] ;
	if (data[*index] == 0xd)
		(*index)++ ;
	if (data[*index] == 0xa)
		(*index)++ ;
	return rv ;
}
static void dopaint(HWND hwnd)
{
	int stop = ((EDITDATA *)GetWindowLong(hwnd,wndoffs))->stop ;
	int index = SendMessage(hwnd,EM_CHARFROMPOS,0,0) & 0xffff,charofs = 0,lines ;
	int i,chars ;
	char *data = GetEditData(hwnd) ;
	PAINTSTRUCT paint ;
	HDC dc ;
	HFONT oldfont ;
	RECT r ;
	TEXTMETRIC tm ;
	HBRUSH brush,graybrush ;
	LOGBRUSH lbrush ;
	HPEN hpen = CreatePen(PS_SOLID,1,0xcccccc),oldpen ;
			while (index && (data[index-1]>= ' ' || data[index-1] == '\t')) {
				index--;
				charofs++ ;
			}
  SendMessage(hwnd,EM_GETRECT,0,(LPARAM)&r) ;
	dc = BeginPaint(hwnd,&paint) ;
	lbrush.lbStyle = BS_SOLID ;
	lbrush.lbColor = GetTextColor(dc) ;
	brush = CreateBrushIndirect(&lbrush) ;
	GetClientRect(hwnd,&r) ;
	oldfont = SelectObject(dc,hNormalFont) ;
	GetTextMetrics(dc, &tm) ;
	lines = r.bottom/tm.tmHeight ;

	FillRect(dc,&paint.rcPaint,brush) ;
	for (i=0 ; i < lines; i++) {
		char buf[256] ;
		chars = linetobuf(data,&index,buf) ;
		if (paint.rcPaint.top <= i*tm.tmHeight && paint.rcPaint.bottom >= (i+1)*tm.tmHeight) {
			doTextOut(dc,i*tm.tmHeight,charofs ,buf,chars,stop) ;
		}
	}
	DeleteObject(brush) ;
	SelectObject(dc,oldfont) ;
	EndPaint(hwnd,&paint) ;
}
LRESULT  CALLBACK _export exeditProc( HWND hwnd, UINT iMessage, WPARAM wParam,
																		LPARAM lParam)
{
	int stop ,index,charofs=0;
	char *data ;
	void *ptr ;
	LRESULT rv ;
	RECT r ;
	HDC dc ;
	switch (iMessage) {
		case EM_SETTABSTOPS:
			stop = 4 * wParam ;
			rv = CallWindowProc(oldproc,hwnd,iMessage,1,(LPARAM)&stop) ;
			((EDITDATA *)GetWindowLong(hwnd,wndoffs))->stop = wParam ;
			return rv ;
		case WM_CREATE:
			rv = CallWindowProc(oldproc,hwnd,iMessage,wParam,lParam) ;
			ptr = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(EDITDATA)) ;
			SetWindowLong(hwnd,wndoffs,(int)ptr) ;
			
			SendMessage(hwnd,WM_SETFONT,(WPARAM)hNormalFont,0) ;
			SendMessage(hwnd,EM_SETTABSTOPS,4,0) ;
			SendMessage(hwnd,EM_SETMARGINS,EC_LEFTMARGIN,LEFTMARGIN) ;
			return rv ;
		case WM_PAINT:
			dopaint(hwnd) ;
			return 0 ;
		case WM_DESTROY:
			HeapFree(GetProcessHeap(),0,(void *)GetWindowLong(hwnd,wndoffs)) ;
			break ;
	}
	return CallWindowProc(oldproc,hwnd,iMessage,wParam,lParam) ;
}

void unregxedit(void)
{
	DeleteObject(hNormalFont) ;
	DeleteObject(backgroundBrush) ;
}
void RegisterXeditWindow(void)
{
		WNDCLASS wc ;
		LOGBRUSH lbrush ;
		lbrush.lbStyle = BS_SOLID ;
		lbrush.lbColor = 0x0000cc ;
		GetClassInfo(0,"edit",&wc) ;
		oldproc = wc.lpfnWndProc ;
		wc.lpfnWndProc = &exeditProc ;
		wc.lpszClassName = "XEDIT" ;
		wc.hInstance = hInstance ;
		wc.cbWndExtra+= (4-wc.cbWndExtra % 4) ;
		wndoffs = wc.cbWndExtra ;
		wc.cbWndExtra += 4 ;
		backgroundBrush = CreateBrushIndirect(&lbrush) ;
		RegisterClass(&wc) ;
		hNormalFont = CreateFont(0,0,0,0,FW_LIGHT,/**/FALSE,FALSE,FALSE,
				ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,
				DRAFT_QUALITY,FIXED_PITCH | FF_DONTCARE,0) ;
}