#define STRICT 
#include <windows.h>
#include <commctrl.h>
#include <commdlg.h>
#include <richedit.h>
#include <stdio.h>
#include "header.h"

extern HANDLE hInstance;
extern HWND hwndWatch , hwndClient, hwndFrame,hwndTab ;
extern int docking ;

HWND hwndError ;
static char szErrorClassName[] = "xccErrorClass" ;
static WNDPROC oldproc ;
static HWND hwndCtrl ;

int getfile(char *start, char *buffer, char end, DWINFO *info)
{
	char *t = buffer,*q=t ;
	int rv = atoi(++buffer) ;
	while (*buffer && isdigit(*buffer))
		buffer++ ;
	if (*buffer == end) {
		while (q > start) {
			if (*(q-1) == ' ')
				break ;
			q-- ;
		}
		strncpy(info->dwName,q,t-q) ;
		info->dwName[t-q] = 0 ;
		q = strrchr(info->dwName, '\\') ;
		if (q)
			strcpy(info->dwTitle,q+1) ;
		else
			strcpy(info->dwTitle,info->dwName) ;
		return rv ;
	}
	return -1 ;
}
void BumpToEditor(HWND hwnd)
{
	HWND wnd ;
	DWINFO info ;
	char name[256],title[256],buffer[256],*t ;
  int lineno ;
	int start ;
	SendMessage(hwnd,EM_GETSEL,(LPARAM) &start,0) ;
	lineno = SendMessage(hwnd,EM_LINEFROMCHAR, start, 0) ;
	*(short *)buffer = 256 ;
	lineno = SendMessage(hwnd,EM_GETLINE,lineno,(LPARAM) buffer) ;
	buffer[lineno] = 0 ;
	lineno = -1 ;
	if (t = strchr(buffer,'(')) {           	
		lineno = getfile(buffer,t,')',&info) ;
	} else if (t = strchr(buffer,':')) {	
		lineno = getfile(buffer,t,':',&info) ;
	}
	if (lineno != -1) {
		info.dwLineNo = lineno ;
		CreateDrawWindow(&info) ;
	}
	
}
LRESULT  CALLBACK _export buildEditProc( HWND hwnd, UINT iMessage, WPARAM wParam,
																		LPARAM lParam)

{
	char buffer[256] ;
	int pos, chars,line ;
	LRESULT rv ;
	switch(iMessage) {
      case WM_LBUTTONDOWN:
         *(short *)buffer = 256 ;
         pos = SendMessage(hwnd, EM_CHARFROMPOS,0,lParam) ;
         line = HIWORD(pos) ;
			chars = SendMessage(hwnd, EM_GETLINE, line, (LPARAM) &buffer) ;
			pos = SendMessage(hwnd, EM_LINEINDEX, line,0) ;
         SendMessage(hwnd,EM_SETSEL,pos,pos+chars) ;
			
			BumpToEditor(hwnd) ;
			return 0 ;
      case WM_RBUTTONDOWN:
         {
            HMENU  menu  = LoadMenu( hInstance, "BUILDMENU" ) ;
            HMENU popup = GetSubMenu( menu, 0 );
            POINT pos ;
            GetCursorPos( &pos );
            TrackPopupMenuEx( popup, TPM_BOTTOMALIGN | TPM_LEFTBUTTON,
                     pos.x, pos.y, hwndFrame, NULL );
            DestroyMenu( menu );
         }
         return 0 ;
      case WM_LBUTTONDBLCLK:
      case WM_LBUTTONUP:
      case WM_RBUTTONUP:
      case WM_RBUTTONDBLCLK:
			return 0 ;
	}
	return CallWindowProc(oldproc,hwnd,iMessage,wParam,lParam) ;
}
LRESULT  CALLBACK _export errorProc( HWND hwnd, UINT iMessage, WPARAM wParam,
																		LPARAM lParam)
{
	static HWND hsubwnd ;
   RECT r,r1, *pr ;
	switch(iMessage) {
		case WM_SYSCOMMAND :
         if (wParam == SC_CLOSE) {
				SendMessage(hwnd,WM_CLOSE,0,0) ;
         }
			break ;
		case WM_COMMAND:
//			switch(LOWORD(wParam)) {
//			}
			break ;
		case WM_SETTEXT:
			if (!lParam)
				SendMessage(hsubwnd,WM_SETTEXT,0,(LPARAM)"") ;
			else {
				int index = SendMessage(hsubwnd, EM_LINEINDEX,0x7fffffff,0);
				SendMessage(hsubwnd,EM_HIDESELECTION,1,0) ;
				SendMessage(hsubwnd,EM_SETSEL,index,index) ;
				SendMessage(hsubwnd,EM_REPLACESEL,FALSE,lParam) ;
				SendMessage(hsubwnd,EM_HIDESELECTION,0,0) ;
				SendMessage(hsubwnd,EM_SCROLLCARET,0,0) ;
			}
			return 0 ;
		case WM_SETFOCUS:
			SendMessage(hwndFrame,WM_REDRAWTOOLBAR,0,0) ;
			SendMessage(hsubwnd, WM_SETFOCUS,wParam,lParam) ;
			break ;
		case WM_CREATE:
			hwndError = hwnd ;
			GetClientRect(hwnd,&r) ;
         hwndCtrl = CreateControlWindow(hwndFrame,hwnd,&r,TRUE) ;
         GetClientRect(hwnd,&r) ;
         SendMessage(hwndCtrl,LCF_ADJUSTRECT,0,(LPARAM)&r) ;
         hsubwnd = CreateWindowEx(0,"XBUILDEDIT",0,WS_CHILD + WS_VISIBLE +
                     WS_VSCROLL + ES_NOHIDESEL + WS_BORDER +
							ES_LEFT + ES_MULTILINE,
                     r.left,r.top,r.right-r.left,r.bottom-r.top,                                    
                     hwndCtrl,(HMENU)ID_EDITCHILD,hInstance,0);              
//         SendMessage(hsubwnd,EM_SETREADONLY,1,0) ;
			return 0 ;
		case WM_CLOSE:
         docking |= HF_ERROR ;
         if (docking & DF_ERROR) {
            if (docking & DF_PROJECT) {
               GetRelativeRect(hwndFrame,hwndTab,&r) ;
               GetFrameInternalRect(&r1) ;
               r.bottom = r1.bottom ;
               MoveWindow(hwndTab,r.left,r.top,r.right-r.left,r.bottom-r.top,TRUE) ;
            }
            if (docking & DF_WATCH) {
               GetRelativeRect(hwndFrame,hwndWatch,&r) ;
               GetFrameInternalRect(&r1) ;
               r.bottom = r1.bottom ;
               MoveWindow(hwndWatch,r.left,r.top,r.right-r.left,r.bottom-r.top,TRUE) ;
            }
         }
         ShowWindow(hwndError,SW_HIDE) ;
         PostMessage(hwndFrame,WM_REDOSIZING,0,0) ;
			return 0 ;
		case WM_DESTROY:
         DestroyWindow(hsubwnd) ;
         DestroyWindow(hwndCtrl) ;
			break ;
		case WM_SIZE:       
         MoveWindow(hwndCtrl,0,0,LOWORD(lParam),HIWORD(lParam),TRUE) ;
         r.left = 0 ;
         r.right = LOWORD(lParam) ;
         r.top = 0 ;
         r.bottom = HIWORD(lParam) ;
         SendMessage(hwndCtrl,LCF_ADJUSTRECT,0,(LPARAM)&r) ;
         MoveWindow(hsubwnd,r.left,r.top,r.right-r.left,r.bottom-r.top,TRUE) ;
			break ;
      case WM_MOVING:
         pr = (RECT *)lParam ;
         GetRelativeRect(hwndFrame,hwnd,&r) ;
         if (!memcmp(pr,&r,sizeof(r)))
            break ;
         GetFrameInternalRect(&r) ;
         if (pr->bottom < r.bottom - 5) {
            if (r.top > pr->top) {
               pr->bottom = r.top + pr->bottom - pr->top ;
               pr->top = r.top ;
            }
            pr->right = pr->left + 300 ;
         } else {
               pr->top = r.bottom - (pr->bottom-pr->top) ;
               pr->bottom = r.bottom ;
               pr->right = r.right ;
               pr->left = r.left ;
         }
         
         break ;
      case WM_SIZING:
         if (docking & DF_ERROR)
            if (wParam != WMSZ_TOP)
               GetRelativeRect(hwndFrame,hwnd, (RECT *)lParam) ;
         break ;
      case WN_ENDMOVE:
         pr = (RECT *)lParam ;
         GetFrameInternalRect(&r) ;
         if (pr->bottom == r.bottom ) {
            docking |= DF_ERROR ;
         } else {
            docking &= ~DF_ERROR ;
            if ((docking & DF_PROJECT) && !(docking & HF_PROJECT)) {
               GetRelativeRect(hwndFrame,hwndClient,&r1) ;
               if (pr->left < r1.left)
                  break ;
               pr->left -= r1.left ;
               pr->right -= r1.left ;
               pr->top -= r1.top ;
               pr->bottom -= r1.top ;
            } else {
               pr->left -= r.left ;
               pr->right -= r.left ;
               pr->top -= r.top ;
               pr->bottom -= r.top ;
            }
         }
         SendMessage(hwndFrame, WM_REDOSIZING, 0, 0) ;
         MoveWindow(hwnd,pr->left, pr->top, pr->right-pr->left, pr->bottom-pr->top, TRUE) ;
         if (docking & DF_PROJECT) {
            GetRelativeRect(hwndFrame,hwndTab,&r1) ;
            if (docking & DF_ERROR)
                  MoveWindow(hwndTab,r1.left,r1.top,r1.right-r1.left,pr->top-r.top, TRUE) ;
            else
                  MoveWindow(hwndTab,r1.left,r1.top,r1.right-r1.left,r.bottom-r1.top, TRUE) ;
         }
         if (docking & DF_WATCH) {
            GetRelativeRect(hwndFrame,hwndWatch,&r1) ;
            if (docking & DF_ERROR)
                  MoveWindow(hwndWatch,r1.left,r1.top,r1.right-r1.left,pr->top-r.top, TRUE) ;
            else
                  MoveWindow(hwndWatch,r1.left,r1.top,r1.right-r1.left,r.bottom-r1.top, TRUE) ;
         }
         
         break ;
		default: 
			break ;
	}
	return DefMDIChildProc(hwnd,iMessage,wParam,lParam) ;
}
void RegisterErrorWindow(void)
{
		WNDCLASS wc ;
      wc.style = 0;
		wc.lpfnWndProc = &errorProc ;
		wc.cbClsExtra = 0;
		wc.cbWndExtra = 0;
		wc.hInstance = hInstance ;
		wc.hIcon = LoadIcon(0,IDI_APPLICATION) ;
		wc.hCursor = LoadCursor(0,IDC_ARROW) ;
		wc.hbrBackground = GetStockObject(WHITE_BRUSH) ;
		wc.lpszMenuName = 0 ;
		wc.lpszClassName = szErrorClassName ;
		RegisterClass(&wc) ;

		GetClassInfo(0,"edit",&wc) ;
		oldproc = wc.lpfnWndProc ;
		wc.lpfnWndProc = &buildEditProc ;
		wc.lpszClassName = "XBUILDEDIT" ;
		wc.hInstance = hInstance ;
		RegisterClass(&wc) ;


}
void CreateErrorWindow(void)
{
		RECT r ;
      if (hwndError)
         return ;
      if (docking & DF_ERROR) {
         POINT pt ;
         GetFrameInternalRect(&r) ;
         r.top = 4 * r.bottom/5 ;
         hwndError = CreateWindowEx( 0, szErrorClassName, "Build window",
            WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | WS_DLGFRAME,
            r.left,                               
            r.top,
            r.right-r.left,
            r.bottom-r.top, hwndFrame, 0 ,hInstance, 0) ;
         PostMessage(hwndFrame,WM_REDOSIZING,0,0) ;
      } else {
         MDICREATESTRUCT mc ;
         GetFrameInternalRect(&r) ;
         mc.szClass = szErrorClassName ;
         mc.szTitle = "Build window" ;
         mc.hOwner = hInstance ;
         mc.x = 0 ;
         mc.y = r.bottom*4/5 ;
         mc.cx = r.right;
         mc.cy = r.bottom/5;
         mc.style = WS_CHILD ;
         mc.lParam = 0 ;
         ShowWindow((HWND)SendMessage(hwndClient,WM_MDICREATE,0,(LPARAM)&mc), SW_HIDE) ;
      }
}