/* 
   Copyright 2001-2003 Free Software Foundation, Inc.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
   02111-1307, USA.  

   You may contact the author at:

   mailto::camille@bluegrass.net

   or by snail mail at:

   David Lindauer
   850 Washburn Ave Apt 99
   Louisville, KY 40222
**********************************************************************

ERROR.C holds the functionality for the several tabs on the ERROR window.
These tabs include the 'build' tab, the 'debug' tab, and two 'find in
files' tabs.  The functionality is primarily performed by superclassing
the rich edit control four times, once for each tab.  The window proc
provides an interface for automatically switching tabs, or clearing the
windows out.

**********************************************************************
*/
#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 ;

HWND hwndError ;
static char szErrorClassName[] = "xccErrorClass" ;
static WNDPROC oldproc ;
static HWND hwndCtrl, hwndTabCtrl ;
static LOGFONT Boldfontdata = {
   14,0,0,0,FW_BOLD,FALSE,FALSE,FALSE,ANSI_CHARSET,OUT_DEFAULT_PRECIS,
   CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FF_MODERN | FF_DONTCARE,
   "Arial"
} ;
static LOGFONT Normalfontdata = {
   14,0,0,0,FW_NORMAL,FALSE,FALSE,FALSE,ANSI_CHARSET,OUT_DEFAULT_PRECIS,
   CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FF_MODERN | FF_DONTCARE,
   "Arial"
} ;
static char *nameTags[] = { "Build", "Debug", "Find in Files 1", "Find in Files 2"} ;
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 = FindRealLine(info.dwName,lineno) ;
		CreateDrawWindow(&info) ;
	}
	
}
void ScanForTags( int tagid, HWND hwnd)
{
   int lines = SendMessage(hwnd,EM_GETLINECOUNT,0,0) ;
   int i,lineno ;
   DWINFO info ;
   char buffer[256],*t ;
   for (i = 0; i < lines; i++) {
      SendMessage(hwnd,EM_GETLINE,i,(LPARAM)buffer) ;
      lineno = -1 ;
      if (t = strchr(buffer,'(')) {             
         lineno = getfile(buffer,t,')',&info) ;
      } else if (t = strchr(buffer,':')) {   
         lineno = getfile(buffer,t,':',&info) ;
      }
      if (lineno != -1)
         Tag(tagid,info.dwName,lineno, 0,0,0,0) ;
   }
}
LRESULT  CALLBACK _export buildEditProc( HWND hwnd, UINT iMessage, WPARAM wParam,
																		LPARAM lParam)

{
	char buffer[256] ;
   int pos, chars,line,i ;
	LRESULT rv ;
   POINTL point ;
   HBRUSH bk ;
   RECT r ;
	switch(iMessage) {
      case WM_CREATE:
         rv = CallWindowProc(oldproc,hwnd,iMessage,wParam,lParam) ;
//         SendMessage(hwnd,EM_NOCOLORIZE,0,0) ;
         return rv ;
      case WM_LBUTTONDOWN:
         *(short *)buffer = 256 ;
         point.x = LOWORD(lParam) ;
         point.y = HIWORD(lParam) ;
         pos = SendMessage(hwnd, EM_CHARFROMPOS,0,(LPARAM)&point) ;
         line = SendMessage(hwnd,EM_LINEFROMCHAR,pos,0) ;
         i = SendMessage(hwnd, EM_GETLINE, line, (LPARAM) &buffer) ;
         chars = 0 ; // richedit 1.0 was tacking things on the end...
         while(i-- && buffer[chars] > 31)
            chars++ ;
			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 hsubwnds[4] ; // build, debug, find1, find2
   static int index ;
   static HFONT tabBoldFont, tabNormalFont ;
   TC_ITEM tie ;
   NMHDR *h ;
   DRAWITEMSTRUCT *dr ;
   HFONT font ;
   RECT r,r1, *pr ;
	switch(iMessage) {
		case WM_SYSCOMMAND :
         if (wParam == SC_CLOSE) {
				SendMessage(hwnd,WM_CLOSE,0,0) ;
         }
			break ;
		case WM_NOTIFY:
         h = (NMHDR *)lParam ;
         switch(h->code) {
            case TCN_SELCHANGE:
               ShowWindow(hsubwnds[index],SW_HIDE) ;
               index = TabCtrl_GetCurSel(hwndTabCtrl) ;
               ShowWindow(hsubwnds[index],SW_SHOW) ;
               break ;
         }
			break ;
		case WM_COMMAND:
//			switch(LOWORD(wParam)) {
//			}
			break ;
      case WM_DRAWITEM:
         dr = (DRAWITEMSTRUCT *)lParam ;
         if (dr->itemState & ODS_SELECTED)
            font = tabBoldFont ;
         else
            font = tabNormalFont ;
         font = SelectObject(dr->hDC,font) ;
         TextOut(dr->hDC,dr->rcItem.left+4,dr->rcItem.bottom-16,nameTags[dr->itemID],strlen(nameTags[dr->itemID])) ;
         font = SelectObject(dr->hDC,font) ;
         break ;
		case WM_SETTEXT:
			if (!lParam)
            SendMessage(hsubwnds[wParam],WM_SETTEXT,0,(LPARAM)"") ;
			else {
            int lindex = SendMessage(hsubwnds[wParam], EM_LINEINDEX,0x7fffffff,0);
            SendMessage(hsubwnds[wParam],EM_HIDESELECTION,1,0) ;
            SendMessage(hsubwnds[wParam],EM_SETSEL,lindex,lindex) ;
            SendMessage(hsubwnds[wParam],EM_REPLACESEL,FALSE,lParam) ;
            SendMessage(hsubwnds[wParam],EM_HIDESELECTION,0,0) ;
            SendMessage(hsubwnds[wParam],EM_SCROLLCARET,0,0) ;
            
			}
			return 0 ;
		case WM_SETFOCUS:
			SendMessage(hwndFrame,WM_REDRAWTOOLBAR,0,0) ;
         SendMessage(hsubwnds[index], WM_SETFOCUS,wParam,lParam) ;
			break ;
		case WM_CREATE:
			hwndError = hwnd ;
			GetClientRect(hwnd,&r) ;
         hwndCtrl = CreateControlWindow(DID_ERRORWND,hwnd,&r,(int)((LPMDICREATESTRUCT)(*(int *)lParam))->lParam) ;
         SendMessage(hwndCtrl,LCF_ADJUSTRECT,0,(LPARAM)&r) ;
         tabBoldFont = CreateFontIndirect(&Boldfontdata) ;
         tabNormalFont = CreateFontIndirect(&Normalfontdata) ;
#ifndef TCS_BOTTOM
#define TCS_BOTTOM 2
#endif
         hwndTabCtrl = CreateWindow(WC_TABCONTROL, 0,
            WS_CHILD + WS_CLIPSIBLINGS + WS_VISIBLE + WS_DLGFRAME + TCS_OWNERDRAWFIXED + TCS_FOCUSNEVER + TCS_BOTTOM, 
            r.left,r.top,r.right-r.left,r.bottom-r.top,
            hwndCtrl, 0 ,hInstance,0)  ;
         OffsetRect(&r,-r.left,-r.top) ;
         TabCtrl_AdjustRect(hwndTabCtrl,FALSE, &r) ;
         hsubwnds[0] = 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,                                    
                     hwndTabCtrl,(HMENU)ID_EDITCHILD,hInstance,0);              
         hsubwnds[1] = CreateWindowEx(0,"XBUILDEDIT",0,WS_CHILD +
                     WS_VSCROLL + ES_NOHIDESEL + WS_BORDER +
							ES_LEFT + ES_MULTILINE,
                     r.left,r.top,r.right-r.left,r.bottom-r.top,                                    
                     hwndTabCtrl,(HMENU)ID_EDITCHILD,hInstance,0);              
         hsubwnds[2] = CreateWindowEx(0,"XBUILDEDIT",0,WS_CHILD +
                     WS_VSCROLL + ES_NOHIDESEL + WS_BORDER +
							ES_LEFT + ES_MULTILINE,
                     r.left,r.top,r.right-r.left,r.bottom-r.top,                                    
                     hwndTabCtrl,(HMENU)ID_EDITCHILD,hInstance,0);              
         hsubwnds[3] = CreateWindowEx(0,"XBUILDEDIT",0,WS_CHILD +
                     WS_VSCROLL + ES_NOHIDESEL + WS_BORDER +
							ES_LEFT + ES_MULTILINE,
                     r.left,r.top,r.right-r.left,r.bottom-r.top,                                    
                     hwndTabCtrl,(HMENU)ID_EDITCHILD,hInstance,0);              
         SendMessage(hsubwnds[0],EM_LIMITTEXT,4*65536,0) ;
         SendMessage(hsubwnds[1],EM_LIMITTEXT,4*65536,0) ;
         SendMessage(hsubwnds[2],EM_LIMITTEXT,4*65536,0) ;
         SendMessage(hsubwnds[3],EM_LIMITTEXT,4*65536,0) ;
         SendMessage(hsubwnds[0], WM_SETFONT, (WPARAM)tabNormalFont, 0) ;
         SendMessage(hsubwnds[1], WM_SETFONT, (WPARAM)tabNormalFont, 0) ;
         SendMessage(hsubwnds[2], WM_SETFONT, (WPARAM)tabNormalFont, 0) ;
         SendMessage(hsubwnds[3], WM_SETFONT, (WPARAM)tabNormalFont, 0) ;
         tie.mask = TCIF_TEXT ;
         tie.iImage = -1 ;
         tie.pszText  = nameTags[0] ;
         TabCtrl_InsertItem(hwndTabCtrl,0, &tie) ;
         tie.mask = TCIF_TEXT ;
         tie.iImage = -1 ;
         tie.pszText  = nameTags[1] ;
         TabCtrl_InsertItem(hwndTabCtrl,1, &tie) ;
         tie.mask = TCIF_TEXT ;
         tie.iImage = -1 ;
         tie.pszText  = nameTags[2] ;
         TabCtrl_InsertItem(hwndTabCtrl,2, &tie) ;
         tie.mask = TCIF_TEXT ;
         tie.iImage = -1 ;
         tie.pszText  = nameTags[3] ;
         TabCtrl_InsertItem(hwndTabCtrl,3, &tie) ;
			return 0 ;
		case WM_CLOSE:
         dmgrHideWindow(DID_ERRORWND,TRUE );
			return 0 ;
		case WM_DESTROY:
         dmgrRemoveClient((CCW_params *)GetWindowLong(hwndCtrl,0)) ;
         DestroyWindow(hwndTabCtrl) ;
         DestroyWindow(hsubwnds[0]) ;
         DestroyWindow(hsubwnds[1]) ;
         DestroyWindow(hsubwnds[2]) ;
         DestroyWindow(hsubwnds[3]) ;
         DestroyWindow(hwndCtrl) ;
			break ;
      case WM_SELERRWINDOW:
         ShowWindow(hsubwnds[index],SW_HIDE) ;
         index = (int)lParam ;
         SendMessage(hwnd,WM_SETTEXT,index,0) ;
         ShowWindow(hsubwnds[index],SW_SHOW) ;
         TabCtrl_SetCurSel(hwndTabCtrl,index) ;
         break ;
      case WM_ERRDONESCAN:
         TagRemoveAll(lParam == ERR_FIND1_WINDOW ? TAG_FIF1 : TAG_FIF2) ;
         ScanForTags(lParam == ERR_FIND1_WINDOW ? TAG_FIF1 : TAG_FIF2, lParam == ERR_FIND1_WINDOW ? hsubwnds[2] : hsubwnds[3]) ;
         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(hwndTabCtrl,r.left,r.top,r.right-r.left,r.bottom-r.top,TRUE) ;
         GetClientRect(hwndTabCtrl,&r) ;
//         OffsetRect(&r,-r.left,-r.top) ;
         TabCtrl_AdjustRect(hwndTabCtrl,FALSE, &r) ;
         MoveWindow(hsubwnds[0],r.left,r.top,r.right-r.left,r.bottom-r.top,TRUE) ;
         MoveWindow(hsubwnds[1],r.left,r.top,r.right-r.left,r.bottom-r.top,TRUE) ;
         MoveWindow(hsubwnds[2],r.left,r.top,r.right-r.left,r.bottom-r.top,TRUE) ;
         MoveWindow(hsubwnds[3],r.left,r.top,r.right-r.left,r.bottom-r.top,TRUE) ;
			break ;
		default: 
			break ;
	}
	return DefMDIChildProc(hwnd,iMessage,wParam,lParam) ;
}
void RegisterErrorWindow(void)
{
		WNDCLASS wc ;
      memset(&wc,0,sizeof(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,"richedit",&wc) ;
		oldproc = wc.lpfnWndProc ;
		wc.lpfnWndProc = &buildEditProc ;
		wc.lpszClassName = "XBUILDEDIT" ;
		wc.hInstance = hInstance ;
      wc.hbrBackground = 0 ;
		RegisterClass(&wc) ;


}
void CreateErrorWindow(void)
{
      MDICREATESTRUCT mc ;
		RECT r ;
      if (hwndError)
         return ;
         mc.szClass = szErrorClassName ;
         mc.szTitle = "Build window" ;
         mc.hOwner = hInstance ;
         mc.x = CW_USEDEFAULT ;
         mc.y = CW_USEDEFAULT ;
         mc.cx = 200;
         mc.cy = 200;
         mc.style = WS_CHILD | WS_DLGFRAME;
         mc.lParam = (LPARAM)0 ;
         hwndError = (HWND)SendMessage(hwndClient,WM_MDICREATE,0,(LPARAM)&mc) ;
}