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

**********************************************************************

EDITOR.C superclasses the xedit control, to provide functionality
such as the right-click menu, loading and saving files to disk, and
loading and saving the parts of the project file related to edit windows.
IT also holds the code for the find and find and replace popups.

**********************************************************************
*/
#include <windows.h>
#include <commctrl.h>
#include <commdlg.h>
#include <richedit.h>
#include <stdio.h>

#include "header.h"
#include <ctype.h>
#include "..\gnu_regex\regex.h"

#define EDITOR_OFFSET 35
HWND CreateDrawWindow(DWINFO *baseinfo) ;

extern HWND hwndSourceTab ;
extern LOGFONT EditFont ;
extern HINSTANCE hInstance ;
extern HWND hwndClient,hwndStatus,hwndFrame,hwndASM ;
extern HANDLE hMenuMain ;
extern int iFindMessage ;
extern char szSourceFilter[] ;
extern COLORREF keywordColor ;
extern COLORREF numberColor  ;
extern COLORREF commentColor ;
extern COLORREF stringColor ;
extern COLORREF escapeColor ;
extern COLORREF backgroundColor ;
extern COLORREF textColor ;
extern int custColors[16] ;
extern enum DebugState uState ;

extern int tabs ;
HWND hwndFind ;
static char szDrawClassName[] = "xccDrawClass" ;
int childxpos,childypos ; 
int numberofdrawwindows ;
int editFlags = BACKUP_FILES|BACKUP_PROJECTS ;
int findflags = 12 ;
int replaceflags = 4 ;

char *findhist1[MAX_COMBO_HISTORY] ;
char *findhist2[MAX_COMBO_HISTORY] ;
char *replacehist[MAX_COMBO_HISTORY] ;

static HBITMAP pcBitmap, stoppcBitmap ;
static HBITMAP tagBmps[TAG_MAX] ;
static char szUntitled[] = "Untitled" ;
static DWINFO *newInfo ;
static   char finding,findbuffer[256],replacebuffer[256],findbuffer2[256] ;
static	FINDREPLACE find ;
static	FINDREPLACE replace ;
static int findpos,found,lastfound ;
HANDLE children[MAX_CHILDREN] ;


int xstricmpz(char *str1, char *str2)
{
	while (*str2)
		if (toupper(*str1++) != toupper(*str2++))
			return 1 ;
	return *str1 != *str2 ;
}
int xstricmp(char *str1, char *str2)
{
	while (*str2)
		if (toupper(*str1++) != toupper(*str2++))
			return 1 ;
	return 0 ;
}
char *stristr(char *str1, char *str2)
{
	int l = strlen(str2) ;
	while(*str1) {
		if (!xstricmp(str1,str2))
			return str1 ;
		str1++ ;
	}
	return 0 ;
}
int ReadNum(char **p)
{
	int rv ;
	if (!**p)
		return 0 ;
	while (**p == ' ')
		(*p)++ ;
	rv = atoi(*p) ;
	while (**p && **p != ' ')
		(*p)++ ;
	return rv ;
}
int RestoreWindows(FILE *in, int projectVersion)
{
	MDICREATESTRUCT mc ;
	static DWINFO info ;
	char buf[256] ;
	int i ;
	if (ReadString(buf,in,"<COLORS>"))
		return 1 ;
	if (ReadString(buf,in,0))
		return 1 ;
	sscanf(buf,"%X",&keywordColor );
	if (ReadString(buf,in,0))
		return 1 ;
	sscanf(buf,"%X",&numberColor );
	if (ReadString(buf,in,0))
		return 1 ;
	sscanf(buf,"%X",&commentColor );
	if (ReadString(buf,in,0))
		return 1 ;
	sscanf(buf,"%X",&stringColor );
	if (ReadString(buf,in,0))
		return 1 ;
	sscanf(buf,"%X",&escapeColor );
	if (ReadString(buf,in,0))
		return 1 ;
	sscanf(buf,"%X",&backgroundColor );
	if (ReadString(buf,in,0))
		return 1 ;
	sscanf(buf,"%X",&textColor );
	for (i=0; i < 16; i++) {
		if (ReadString(buf,in,0))
			return 1 ;
		sscanf(buf,"%X",&custColors[i] );
	}
	if (ReadString(buf,in,"</COLORS>"))
		return 1 ;
	if (ReadString(buf,in,"<TABS"))
		return 1 ;
	tabs = atoi(buf + 6) ;
	if (ReadString(buf,in,"<EDITOR "))
		return 1 ;
	sscanf(buf+ 8,"%x",&editFlags );
	if (ReadString(buf,in,"<WINDOWS>"))
		return 1 ;
	while (1) {
		int i = 0 ;
		char *p = buf ;
		
		if (ReadString(buf,in,0))
			return 1 ;
		if (buf[0] == '<')
			break ;
		memset(&info,0,sizeof(info)) ;
		while (*p && *p != ';')
			info.dwName[i++] = *p++ ;
      if (projectVersion >= 2)
         abspath(info.dwName) ;
		i = 0 ;
		if (*p)
			p++ ;
		while (*p && *p != ' ')
			info.dwTitle[i++] = *p++ ;
		newInfo = &info ;

		mc.szClass = szDrawClassName ;
		mc.szTitle = szUntitled ;
		mc.hOwner = hInstance ;
		mc.x = ReadNum(&p) ;
		mc.y = ReadNum(&p) ;
		mc.cx = ReadNum(&p);
		mc.cy = ReadNum(&p);
      mc.style = WS_CHILD | WS_VISIBLE | WS_OVERLAPPEDWINDOW |  WS_SYSMENU | WS_SIZEBOX|WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
		mc.lParam = 0 ;
      newInfo->dwLineNo = ReadNum(&p) ;
      SendMessage(hwndClient,WM_MDICREATE,0,(LPARAM)&mc) ;
		Sleep(250) ;	
	}
	if (xstricmp(buf,"</WINDOWS>"))
		return 1 ;
}
void SaveWindows(FILE *out)
{
	int i;
	fprintf(out,"<COLORS>\n") ;
	fprintf(out,"%08x\n",keywordColor) ;
	fprintf(out,"%08x\n",numberColor) ;
	fprintf(out,"%08x\n",commentColor) ;
	fprintf(out,"%08x\n",stringColor) ;
	fprintf(out,"%08x\n",escapeColor) ;
	fprintf(out,"%08x\n",backgroundColor) ;
	fprintf(out,"%08x\n",textColor) ;
	for (i=0; i < 16; i++)
		fprintf(out,"%08x\n",custColors[i]) ;
	fprintf(out,"</COLORS>\n") ;
	fprintf(out,"<TABS %d>\n",tabs) ;
	fprintf(out,"<EDITOR %x>\n",editFlags) ;
	fprintf(out,"<WINDOWS>\n") ;
	for (i=0; i < numberofdrawwindows; i++) {
		RECT r ;
		POINT p ;
		int startpos ;
      struct minmax {
         int min,max ;
      } charinfo ;
      WINDOWPLACEMENT placement ;
		DWINFO *info = (DWINFO *)GetWindowLong(children[i],0) ;
      SendMessage(GetDlgItem(children[i],ID_EDITCHILD),EM_EXGETSEL,0,(WPARAM) &charinfo) ;
      startpos = SendMessage(GetDlgItem(children[i],ID_EDITCHILD),EM_LINEFROMCHAR, charinfo.min,0 ) ;
      placement.length = sizeof(placement) ;
      GetWindowPlacement(children[i],&placement) ;
      p.x = placement.rcNormalPosition.left ;
      p.y = placement.rcNormalPosition.top ;
//      ScreenToClient(hwndClient,&p) ;
      fprintf(out,"%s;%s %d %d %d %d %d\n",relpath(info->dwName),info->dwTitle,
            p.x,p.y,placement.rcNormalPosition.right-placement.rcNormalPosition.left,
            placement.rcNormalPosition.bottom-placement.rcNormalPosition.top,startpos+1) ;    
	}
	fprintf(out,"</WINDOWS>\n") ;
}
void ApplyEditSettings(void)
{
	int i ;
	for (i=0; i < numberofdrawwindows; i++) 
      PostMessage(GetDlgItem(children[i],ID_EDITCHILD),WM_SETEDITORSETTINGS,0,0) ;

}
void ApplyFontSettings(LPLOGFONT lf)
{
	int i ;
   memcpy(&EditFont,lf,sizeof(EditFont)) ;
   for (i=0; i < numberofdrawwindows; i++)  {
      HFONT fnt = CreateFontIndirect(&EditFont) ;
      PostMessage(GetDlgItem(children[i],ID_EDITCHILD),WM_SETFONT,(WPARAM)fnt,0) ;
   }
}
void CheckEditWindowChanged(void)
{
	int i ;
	for (i=0; i < numberofdrawwindows; i++) 
      PostMessage(children[i],WM_CHECKCHANGE,0,0) ;
}
void InvalidateByName(char *name)
{
   int i ;
   DWINFO info ;
   strcpy(info.dwName,name) ;
   for (i=0; i < numberofdrawwindows; i++)
      if (SendMessage(children[i],WM_COMMAND,ID_QUERYHASFILE,(LPARAM)&info))
         InvalidateRect(children[i],0,0) ;
}
int ApplyBreakAddress(char *module, int linenum)
{
   char nmodule[260] ;
	int i ;
   nmodule[0] = 0 ;
   if (linenum) {
      char *p ;
      static DWINFO x ;
      FindModuleName(nmodule, module) ;
      strcpy(x.dwName, nmodule) ;
      p = strrchr(nmodule, '\\') ;
      if (p)
         strcpy(x.dwTitle,p+1) ;
      else
         strcpy(x.dwTitle,nmodule) ;
      x.dwLineNo = 1 ;
      x.breakpointLine = linenum ;
      x.dwLineNo = linenum ;
      CreateDrawWindow(&x) ;
   }
   for (i=0; i < numberofdrawwindows; i++) {
      (HWND)SendMessage(children[i],WM_SETBREAKLINE,(WPARAM)nmodule, linenum) ;
   }
}
int QuerySaveAll(void)
{
	int i;
   for (i=0 ; i < numberofdrawwindows; i++) {
      int rv = SendMessage(children[i],WM_COMMAND,ID_QUERYSAVE,0) ;
      if (rv == IDCANCEL)
         return rv ;
      if (rv == IDYES)
         SendMessage(children[i],WM_COMMAND, IDM_SAVE,0) ;
   }
   return IDYES ;
}
void SaveDrawAll(void)
{
	int i;
	for (i=0; i < numberofdrawwindows; i++) {
		DWINFO *ptr = (DWINFO *)GetWindowLong(children[i],0) ;
      if (SendMessage(ptr->dwHandle,EM_GETMODIFY,0,0))
         SendMessage(children[i],WM_COMMAND, IDM_SAVE,0) ;
	}
}
void CloseAll(void)
{
	int i;
   for (i=numberofdrawwindows-1; i >=0 ; i--)
      SendMessage(children[i],WM_CLOSE,0,0) ;
}
char *GetEditData(HWND hwnd)
{
	int l ;
	char *buf ;
   l = SendMessage(hwnd,WM_GETTEXTLENGTH,0,0) ;
	buf = malloc(l+1) ;
	if (!buf) {
		return 0;
	}
  SendMessage(hwnd,WM_GETTEXT,l+1,(LPARAM)buf) ;
	return buf ;
}
int SetEditData(HWND hwnd, char *buf)
{
   SendMessage(GetDlgItem(hwnd,ID_EDITCHILD),WM_SETTEXT,0,(LPARAM)buf) ;
	free(buf) ;
	return TRUE ;
}
void backup(char *name)
{
	char newname[256],buffer[512] ;
	char *s ;
   HANDLE in,out ;
	int size ;
	BY_HANDLE_FILE_INFORMATION info ;
	strcpy(newname,name) ;
	s = strrchr(newname,'.') ;
	if (s)
      if (!xstricmp(s,".prj"))
         strcpy(s,".bpj") ;
      else
         strcpy(s,".bak") ;
	else
		strcat(newname,".bak") ;

   in = CreateFile(name,GENERIC_READ,0,0,OPEN_EXISTING,0,0) ;
   if (in == INVALID_HANDLE_VALUE)
		return ;
   if (!GetFileInformationByHandle(in,&info)) {
      CloseHandle(in) ;
      return ;
   }
   out = CreateFile(newname,GENERIC_WRITE,0,0,CREATE_ALWAYS,0,0) ;
   if (out == INVALID_HANDLE_VALUE) {
      ExtendedMessageBox("Write Error",0,"Backup file is not accessible") ;
      CloseHandle(in);
      return ;
   }
   while (1) {
      DWORD read,written ;
      if (!ReadFile(in,buffer,512,&read,0) || !read)
         break ;
      WriteFile(out,buffer,read,&written,0) ;
   }
   SetFileTime(out,&info.ftCreationTime, &info.ftLastAccessTime, &info.ftLastWriteTime) ;
   CloseHandle(out) ;
   CloseHandle(in) ;
}
int SaveFile(HWND hwnd, DWINFO *info)
{
	char *buf  = GetEditData(GetDlgItem(hwnd,ID_EDITCHILD)) ;
	FILE *out ;
	int l,i ;
	
	if (editFlags &  BACKUP_FILES)
		backup(info->dwName) ;
	if (!buf)
		return FALSE ;
#ifdef OLD_EDIT_FORMAT
   out = fopen(info->dwName,"wb") ;
#else
   out = fopen(info->dwName,"w") ;
#endif
	if (!out) {
      ExtendedMessageBox("Write Error",0,"Output file is read-only") ;
		free(buf) ;
		return FALSE ;
	}
   fputs(buf,out) ;
	fclose(out) ;
	free(buf) ;
   FileTime(&info->time, info->dwName) ;
	return TRUE ;
}
int LoadFile(HWND hwnd, DWINFO *info)
{
	long size ;
	char *buf ;
#ifdef OLD_EDIT_FORMAT
  FILE *in = fopen(info->dwName,"rb") ;
#else
  FILE *in = fopen(info->dwName,"r") ;
#endif
	if (!in)
		return FALSE ;
	fseek(in,0L,SEEK_END) ;
	fgetpos(in,&size);
   buf = calloc(size+1,1) ;
	if (!buf) {
		fclose(in) ;
		return FALSE ;
	}
	fseek(in,0L,SEEK_SET) ;
   size = fread(buf,1,size,in) ;
   if (size < 0)
      size = 0 ;
   buf[size] = 0 ;
	fclose(in) ;
	SetEditData(hwnd,buf) ;
   SendMessage(info->dwHandle,EM_SETMODIFY,0,0) ;
   if (GetFileAttributes(info->dwName) & FILE_ATTRIBUTE_READONLY)
      SendMessage(info->dwHandle,EM_SETREADONLY,1,0) ;
   FileTime(&info->time, info->dwName) ;
	return TRUE ;

}
#ifdef TEST
BOOL CALLBACK enumfunc(HWND wnd, int param)
{
   FILE *fil = fopen("q","a") ;
   char buf[256],buf2[256] ;
   int id = GetWindowLong(wnd,GWL_ID) ;
   GetClassName(wnd,buf,256) ;
   GetWindowText(wnd,buf2,256) ;
   fprintf(fil,"%s(%s): %d\n",buf2,buf,id) ;
   fclose(fil) ;
   return TRUE ;
}
#endif
/* hook function translates CBN style messaging to EN style messaging */
BOOL CALLBACK findHook(HWND hwnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
   if (iMessage == WM_COMMAND) {
      int l = wParam >> 16 ;
      if (l == CBN_SELENDOK) {
         SendMessage((HWND)lParam, WM_SETMODIFY,1,0) ; // we do this so the edit box will have something in it when the dialog proc checks it
      }
      if (l == CBN_EDITUPDATE || l == CBN_SELENDOK) {
         SendMessage(hwnd,WM_COMMAND,(EN_UPDATE << 16) + (wParam & 0xffff), lParam) ;
      }
      if (l == CBN_EDITCHANGE || l == CBN_SELENDOK) {
         SendMessage(hwnd,WM_COMMAND,(EN_CHANGE << 16) + (wParam & 0xffff), lParam) ;
      }
      if ((wParam & 0xffff) == IDCANCEL)
         goto join ;
   }
   if (iMessage == WM_SYSCOMMAND)
      if (wParam == SC_CLOSE) {
join:
		if (finding) {
			 findflags = 0 ;
          if (IsDlgButtonChecked(hwnd,1040))
				findflags ++ ;
          if (IsDlgButtonChecked(hwnd,1041))
				findflags += 2 ;
          if (IsDlgButtonChecked(hwnd,990))
				findflags += 4 ;
          if (IsWindow(GetDlgItem(hwnd,1057)) && IsDlgButtonChecked(hwnd,1057))
				findflags += 8 ;
          IntToProfile("FindFlags",findflags) ;
		} else {
			 replaceflags = 0 ;
          if (IsDlgButtonChecked(hwnd,1040))
				replaceflags ++ ;
          if (IsDlgButtonChecked(hwnd,1041))
				replaceflags += 2 ;
          if (IsDlgButtonChecked(hwnd,990))
				replaceflags += 4 ;
          if (IsWindow(GetDlgItem(hwnd,1057)) && IsDlgButtonChecked(hwnd,1057))
				replaceflags += 8 ;
          IntToProfile("ReplaceFlags",replaceflags) ;
		}
        hwndFind = 0 ;
      }
   if (iMessage == WM_INITDIALOG) {
	  if (finding) {
	  	if (findflags & 4)
      		CheckDlgButton(hwnd,990,1) ;
	  } else 
	  	if (replaceflags & 4)
      		CheckDlgButton(hwnd,990,1) ;
      return 1 ;
   } else
      return 0 ;
}
void PopFindString(HWND hwnd)
{
   char buf[256] ;
   HWND hwndedit ;
   if (IsWindow(hwndFind)) {
      SetFocus(hwndFind) ;
      return ;
   }
   if (GetWordFromPos(GetDlgItem(hwnd,ID_EDITCHILD),buf,-1,0,0,0) && buf[0])
      strcpy(findbuffer,buf) ;
	find.lStructSize = sizeof(find) ;
   find.hwndOwner = hwndFrame ;
	find.hInstance = hInstance ;
   find.Flags = FR_ENABLETEMPLATE | FR_ENABLEHOOK ;
	if (findflags &1)
		find.Flags |= FR_WHOLEWORD ;
	if (findflags & 2)
      find.Flags |= FR_MATCHCASE ;
	if (findflags & 8)
		find.Flags |= FR_DOWN ;
   find.lpstrFindWhat = findbuffer ;
	find.lpstrReplaceWith = 0 ;
	find .wFindWhatLen = 256 ;
	find .wReplaceWithLen = 0 ;
   find.lpTemplateName = "FINDDLG" ;
   find.lpfnHook = findHook ;
	finding = TRUE ;
	hwndFind = FindText(&find ) ;
   hwndedit = GetDlgItem(hwndFind, 1152) ;
   SubClassHistoryCombo(hwndedit) ;
   SendMessage(hwndedit,WM_SETHISTORY,0,(LPARAM)findhist1) ;
//   EnumChildWindows(hwndFind, (WNDENUMPROC)enumfunc,0) ;
   lastfound = -1 ;
   SendMessage(GetDlgItem(hwnd,ID_EDITCHILD),EM_GETSEL, (WPARAM)&findpos,0) ;
}
void PopReplaceString(HWND hwnd)
{
   DWINFO *p = (DWINFO *)GetWindowLong(hwnd,0) ;
   char buf[256] ;
   HWND hwndedit ;
   if (IsWindow(hwndFind)) {
      SetFocus(hwndFind) ;
      return ;
   }
//   if (GetWordFromPos(GetDlgItem(hwnd,ID_EDITCHILD),buf,-1,0,0,0) && buf[0])
//      strcpy(findbuffer2,buf) ;
	replace.lStructSize = sizeof(replace) ;
   replace.hwndOwner = hwndFrame ;
	replace.hInstance = hInstance ;
   replace.Flags = FR_ENABLETEMPLATE | FR_ENABLEHOOK | FR_DOWN;
	if (replaceflags &1)
		find.Flags |= FR_WHOLEWORD ;
	if (replaceflags & 2)
      find.Flags |= FR_MATCHCASE ;
   replace.lpstrFindWhat = findbuffer2 ;
	replace.lpstrReplaceWith = replacebuffer ;
	replace .wFindWhatLen = 256 ;
	replace .wReplaceWithLen = 256 ;
   replace.lpTemplateName = "REPLACEDLG" ;
   replace.lpfnHook = findHook ;
	finding = FALSE ;
   hwndFind = ReplaceText(&replace ) ;
   hwndedit = GetDlgItem(hwndFind, 1152) ;
   SubClassHistoryCombo(hwndedit) ;
   SendMessage(hwndedit,WM_SETHISTORY,0,(LPARAM)findhist2) ;
   hwndedit = GetDlgItem(hwndFind, 1153) ;
   SubClassHistoryCombo(hwndedit) ;
   SendMessage(hwndedit,WM_SETHISTORY,0,(LPARAM)replacehist) ;
//   EnumChildWindows(hwndFind, (WNDENUMPROC)enumfunc,0) ;
	found = FALSE ;
   lastfound = -1 ;
   SendMessage(GetDlgItem(hwnd,ID_EDITCHILD),EM_GETSEL, (WPARAM)&findpos,0) ;

}
int xfind(FINDREPLACE *find, char *buf, int pos, int *len, struct re_registers **r, int *n)
{
	int flags = find->Flags ;
	int i ;
   if (!find->lpstrFindWhat)
      return -1 ;

	if (pos < 0)
		pos = 0 ;
	
	*len = strlen(find->lpstrFindWhat ) ;
	while (TRUE) {
      if (IsWindow(GetDlgItem(hwndFind,990)) && IsDlgButtonChecked(hwndFind,990)) {
#ifdef XREGEX_POSIX
			regex_t preg ;
			regmatch_t match[1] ;
	        int err = regcomp(&preg,find->lpstrFindWhat,REG_EXTENDED | ((flags & FR_MATCHCASE) ? 0 : REG_ICASE) | REG_NEWLINE) ;
			if (err) {
				char ebuf[256] ;
            	regerror(err,&preg,ebuf,256) ;
				ExtendedMessageBox("Regular Expression Error",0,ebuf) ;
				return -1 ;
			}				
         	if (!regexec(&preg,buf+pos,1,&match,0)) {
            	regfree(&preg) ;   
				*len = match->rm_eo - match->rm_so ;
				pos = match->rm_so + pos + buf ;
			} else {
            	regfree(&preg) ;
				return -1 ;
			}
#else
			// This isn't a full emacs version
			char *err ;
			static struct re_pattern_buffer patbuf ;
         static struct re_registers registers;
			static unsigned char trans[256], fastmap[256] ;
         re_set_syntax(RE_SYNTAX_EMACS | RE_CHAR_CLASSES | RE_INTERVALS) ;
			patbuf.translate = &trans;
			for (i=0;i<256;i++)
				trans[i] = i ;
			if (!(flags & FR_MATCHCASE))
				for (i='a'; i <= 'z'; i++)
					trans[i] = i - 'a' + 'A' ;
			patbuf.fastmap = &fastmap ;
			patbuf.fastmap_accurate = FALSE ;
			err = re_compile_pattern(find->lpstrFindWhat,strlen(find->lpstrFindWhat),
					&patbuf) ;
			if (err) {
				ExtendedMessageBox("Regular Expression Error",0,err) ;
				return -1 ;
			}
			i = strlen(buf) ;
         if (flags & FR_DOWN)
            i = re_search(&patbuf,buf,i,pos,i-pos, & registers) ;
         else
            i = re_search(&patbuf,buf,i,pos,-pos, & registers) ;
			if (i < 0)
				return -1 ;	
         	if (r)
            	*r = &registers ;
	        if (n)
            	*n = patbuf.re_nsub ;
			*len = registers.end[0] - registers.start[0] ;
			pos = registers.start[0] + buf ;
#endif
		}
      else if (flags & FR_DOWN) { 
         if (flags & FR_MATCHCASE)
            pos = (int)strstr(buf+pos,find->lpstrFindWhat);
         else
            pos = (int)stristr(buf+pos,find->lpstrFindWhat);
      } else {
         do {
            int l = strlen(find->lpstrFindWhat) ;
            if (flags & FR_MATCHCASE) {
               if (!strncmp(buf+pos,find->lpstrFindWhat,l))
                  break ;
            } else
               if (!strnicmp(buf+pos,find->lpstrFindWhat,l))
                  break ;
            pos-- ;
         } while (pos>=0) ;
         if (pos < 0)
            pos = 0 ;
         else
            pos = pos + buf ;
      }
		if (pos) {
			pos = (char *)pos - buf ;
			if (flags & FR_WHOLEWORD) {
				if (pos && isalnum(buf[pos-1])) 
					pos += *len ;
				else if (!buf[pos+*len] || !isalnum(buf[pos+*len]))
					return pos ;
				else
					pos += *len ; 
			}
			else return pos ;
		} else
			return -1 ;

	}
	
}
void MoveFindWindow(HWND editwnd, int left, int right)
{
   POINTL ptl, ptr ;
   RECT w, w1, f, s ;
   int th = SendMessage(editwnd, EM_GETTEXTHEIGHT,0,0) ;
   SendMessage(editwnd, EM_POSFROMCHAR,(WPARAM)&ptl,left) ;
   SendMessage(editwnd, EM_POSFROMCHAR,(WPARAM)&ptr,right) ;
   GetWindowRect(editwnd,&w) ;
   GetWindowRect(hwndFind, &f) ;

   memcpy(&w1,&w,sizeof(RECT)) ;

   if (ptl.y < w.bottom - w.top)
      w.bottom = w.top + ptl.y ;
   w.top = w.bottom - th ;
   if (ptr.x < w.right - w.left)
      w.right = w.left + ptr.x ;
   if (ptl.x < w.right - w.left)
      w.left = w.left + ptl.x ;

   if (IntersectRect(&s,&w,&f)) {
      if (w.top - w1.top > (w1.bottom - w1.top)/2) {
         if (w.top - f.top + f.bottom < 0)
            MoveWindow(hwndFind,f.left,w.bottom + th + f.right-f.left,f.right-f.left,f.bottom-f.top,TRUE) ;
         else
            MoveWindow(hwndFind,f.left,w.top - th - f.top + f.bottom,f.right-f.left,f.bottom-f.top,TRUE) ;
      } else {
         MoveWindow(hwndFind,f.left,w.bottom + th,f.right-f.left,f.bottom-f.top,TRUE) ;
      }
   }
}
int FindNextString(HWND hwnd, FINDREPLACE *find,struct re_registers **r, int *n)
{
	char *buf = GetEditData(GetDlgItem(hwnd,ID_EDITCHILD)) ;
	int len ;
	if (buf) {
      int pos ;
      SendMessage(GetDlgItem(hwnd,ID_EDITCHILD),EM_GETSEL, (WPARAM)&pos,0) ;
      if (pos != lastfound && findpos != -1)
         findpos = pos ;
      if (findpos == -1)
         if (find->Flags & FR_DOWN)
            findpos = 0 ;
         else
            findpos = strlen(buf) ;
      findpos = xfind(find, buf,findpos,&len,r,n) ;
      lastfound = findpos ;
		free(buf) ;
		if (findpos > 0) {
         SendMessage(GetDlgItem(hwnd,ID_EDITCHILD), EM_SETSEL,findpos, findpos+len) ;
         SendMessage(GetDlgItem(hwnd,ID_EDITCHILD), EM_SCROLLCARET, 0,0 );
			UpdateWindow(GetDlgItem(hwnd,ID_EDITCHILD)) ;
         if (find->Flags & FR_DOWN)
            findpos += len ;
         else {
            findpos -= len ;
            if (findpos < 0) {
               findpos = 0 ;
               goto done ;
            }
         }
         MoveFindWindow(GetDlgItem(hwnd,ID_EDITCHILD), findpos, findpos + len) ;
		} else {
done:
         SendMessage(GetDlgItem(hwnd,ID_EDITCHILD),EM_SETSEL,-1,0) ;
         if (!(find->Flags & FR_REPLACEALL)) {
//            MessageBeep(MB_OK) ;
            ExtendedMessageBox("Search",MB_TASKMODAL,"No more matches found") ;
            findpos = -1 ;
         }
         return TRUE ;
		}
      return FALSE ;
	}
   return TRUE ;

}
void ReplaceNextString(HWND hwnd, FINDREPLACE *replace)
{
   char buf[256] ;
   int flags ;
   static struct re_registers *registers ;
   int regnum ;
   replace->Flags |= FR_DOWN ;
   flags = replace->Flags ;
	while (TRUE) {
      int notthere = FALSE ;
		if (!found || (flags & FR_FINDNEXT))
         notthere = FindNextString(hwnd,replace,&registers,&regnum) ;
		found = TRUE ;
      if (notthere)
			return ;             
		if (flags & (FR_REPLACE | FR_REPLACEALL)) {
         int readonly = SendMessage(GetDlgItem(hwnd,ID_EDITCHILD), EM_GETREADONLY,0,0) ;
         if (!readonly) {
            if (IsWindow(GetDlgItem(hwndFind,990)) && IsDlgButtonChecked(hwndFind,990)) {
               int i,dest = 0 ;
               char *dta = GetEditData(GetDlgItem(hwnd,ID_EDITCHILD)) ;
               for (i=0; i < strlen(replace->lpstrReplaceWith) && dest < 255; i++) {
                  if (replace->lpstrReplaceWith[i] == '\\') {
                     if (replace->lpstrReplaceWith[++i]) {
                        int index = replace->lpstrReplaceWith[i] ;   
                        if (isdigit(index)) {
                           index -= '0' ;
                           if (dta && index <= regnum) {
                              int j ;
                              for (j = registers->start[index]; j < registers->end[index] && dest < 255; j++)
                                 buf[dest++] = dta[j] ;    
                           }
                        } else
                           buf[dest++] = replace->lpstrReplaceWith[i] ;
                     }
                  } else 
                     buf[dest++] = replace->lpstrReplaceWith[i] ;
               }
               free(dta) ;
               buf[dest] = 0 ;
            } else {
               strcpy(buf,replace->lpstrReplaceWith) ;
            }
            SendMessage(GetDlgItem(hwnd,ID_EDITCHILD), EM_REPLACESEL, 1, (LPARAM) buf) ;
            UpdateWindow(GetDlgItem(hwnd,ID_EDITCHILD)) ;
         }
			findpos += strlen(replace->lpstrReplaceWith) - strlen(replace->lpstrFindWhat) ;
			found = FALSE ;
		}
		if (!(flags & FR_REPLACEALL))
         if (flags & FR_REPLACE) {
            flags &= ~FR_REPLACE ;
            flags |= FR_FINDNEXT ;
         } else
            return ;
	}

}
void drawParams(HWND hwnd)
{
   char buf[512] ;
   int start,ins,col,sel ;
   int readonly = SendMessage(hwnd, EM_GETREADONLY,0,0) ;
   int mod = SendMessage(hwnd, EM_GETMODIFY,0,0);
   SendMessage(hwnd,EM_GETSEL,(WPARAM) &sel,0) ;
   start = SendMessage(hwnd,EM_LINEFROMCHAR,sel,0) ;
   ins = SendMessage(hwnd,EM_GETINSERTSTATUS,0,0) ;
   col = SendMessage(hwnd, EM_GETCOLUMN,0,0) ;
   sprintf(buf,"Line: %d",start+1) ;
   SendMessage(hwndStatus,SB_SETTEXT,1 , (LPARAM)buf) ;
   sprintf(buf,"Col: %d",col+1) ;
   SendMessage(hwndStatus,SB_SETTEXT,2 , (LPARAM)buf) ;
   SendMessage(hwndStatus,SB_SETTEXT,3 , (LPARAM)(ins ? "INS" : "OVR")) ;
   if (readonly)
      SendMessage(hwndStatus,SB_SETTEXT,4 , (LPARAM)("READ-ONLY")) ;
   else
      SendMessage(hwndStatus,SB_SETTEXT,4 , (LPARAM)(mod ? "MODIFIED" : "    ")) ;
   SendMessage(hwndStatus,SB_SETTEXT,0 | SBT_NOBORDERS, (LPARAM)"    ") ;
	
}
void eraseParams(HWND hwnd)
{
   SendMessage(hwndStatus,SB_SETTEXT,1 , (LPARAM)"    ") ;
   SendMessage(hwndStatus,SB_SETTEXT,2 , (LPARAM)"    ") ;
   SendMessage(hwndStatus,SB_SETTEXT,3 , (LPARAM)"    ") ;
   SendMessage(hwndStatus,SB_SETTEXT,4 , (LPARAM)"    ") ;
   
}
int PaintBreakpoints(HWND hwnd, HDC dc, PAINTSTRUCT *paint, RECT *rcl)
{
   HBRUSH graybrush,graybrush1 ;
   RECT r,r1 ;
   int i ;
   int rv = FALSE ;
   HDC hMemDC = CreateCompatibleDC(dc) ;
   DWINFO *ptr = (DWINFO*)GetWindowLong(hwnd,0) ;
   int linenum = SendMessage(ptr->dwHandle,EM_GETFIRSTVISIBLELINE,0,0) + 1;
   int chpos1 = SendMessage(ptr->dwHandle, EM_LINEINDEX,linenum,0) ;
   int ypos ;
   int lines,offset = 0  ;
   int height ;
   short*lt ;
   int lc;
   POINTL pt ;
   SendMessage(ptr->dwHandle, EM_POSFROMCHAR,(WPARAM)&pt,chpos1) ;
   ypos = pt.y ;

   SendMessage(ptr->dwHandle,EM_GETRECT,0,(LPARAM)&r1) ;
   lines = r1.bottom / (height = SendMessage(ptr->dwHandle,EM_GETTEXTHEIGHT,0,0)) ;

   if (ypos < height)
      offset= ypos -height;

   if (uState != notDebugging) {
      lt = GetLineTable(ptr->dwName,&lc) ;
      if (lt) {
         while (lc && *lt < linenum) {
            lc-- ;
            lt++ ;
         }
         if (lc) {
            graybrush = CreateSolidBrush(GetSysColor(COLOR_3DFACE)) ;
            graybrush1 = CreateSolidBrush(0) ;
            for (i=linenum; i <= linenum+lines; i++) {
               int j, drawn = FALSE; 
               r.left = 0 ;
               r.right = 32 ;
               r.top = offset + (i - linenum) * height ;
               r.bottom = r.top + height ;
               for (j = 0; j < lc; j++)
                  if (lt[j] == i) {
                     FillRect(dc,&r,graybrush) ; 
                     drawn = TRUE ;
                     break ;
                  }
               if (!drawn) 
                  FillRect(dc,&r,graybrush1) ;
            }
            DeleteObject(graybrush) ;
            DeleteObject(graybrush1) ;
            rv = TRUE ;
         } else 
            goto fillrect ;
      } else
        goto fillrect ;
   } else {
fillrect:
      graybrush = CreateSolidBrush(GetSysColor(COLOR_3DFACE)) ;
      FillRect(dc,rcl,graybrush) ; 
      DeleteObject(graybrush) ;
   }
   for (i = linenum; i <= linenum + lines; i++) {
      int type = IsTagged(ptr->dwName,i) ;
      if (type != -1) { //  && (type != TAG_BP || uState != notDebugging)) {
         SelectObject(hMemDC,tagBmps[type]) ;
         BitBlt(dc,16,(i - linenum)*height + offset,16,16,hMemDC,0,0,SRCCOPY) ;
      }
   }
   if (ptr->breakpointLine >= linenum && ptr->breakpointLine <= linenum + lines) {
      if (IsTagged(ptr->dwName,ptr->breakpointLine) == TAG_BP)
         SelectObject(hMemDC,stoppcBitmap) ;
      else
         SelectObject(hMemDC,pcBitmap) ;
      BitBlt(dc,16,(ptr->breakpointLine - linenum)*height + offset,16,16,hMemDC,0,0,SRCCOPY) ;
   }
   DeleteDC(hMemDC) ;
}
LRESULT  CALLBACK _export gotoProc( HWND hwnd, UINT iMessage, WPARAM wParam,
																		LPARAM lParam)
{
   char buf[3] ;
	switch(iMessage) {
		case WM_COMMAND:
			if (wParam == IDOK) {
				int i = GetEditFieldValue(hwnd,IDC_GOTO);
				EndDialog(hwnd,i) ;
            break ;
			}
         if (HIWORD(wParam) == EN_CHANGE) {
               DisableControl(hwnd,IDOK,!GetWindowText((HWND)lParam,buf,2)) ;
               break ;
         }
         if (wParam != IDCANCEL)
            break ;
		case WM_CLOSE:
			EndDialog(hwnd,0) ;
			break ;
		case WM_INITDIALOG:
			CenterWindow(hwnd) ;
			SetEditField(hwnd,IDC_GOTO,"") ;
         DisableControl(hwnd,IDOK,1) ;
			break ;
	}
	return 0 ;
}
LRESULT  CALLBACK _export DrawProc( HWND hwnd, UINT iMessage, WPARAM wParam,
																		LPARAM lParam)
{
   DWINFO *ptr,*ptr1 ;
	OPENFILENAME ofn ;
	HDC dc ;
	HPEN hpen,oldpen ;
	RECT r ;
	HBRUSH graybrush ;
	LOGBRUSH lbrush ;
	PAINTSTRUCT paint ;
   int childheight ;
   int startpos, endpos,flag,i ;
   HWND win ;
   FILETIME time ;
   NMHDR *nm ;
   int rv ;
	switch(iMessage) {
      case EN_LINECHANGE:
         ptr = (DWINFO*)GetWindowLong(hwnd,0) ;
         TagLineChange(ptr->dwName,wParam+1,lParam) ;
         GetClientRect(hwnd,&r) ;
         r.right = EDITOR_OFFSET ;
         InvalidateRect(hwnd,&r,0) ;
         break ;
      case WM_NOTIFY:
         nm = (NMHDR *)lParam ;
         if (nm->code == NM_RCLICK) {
               HMENU  menu  = LoadMenu( hInstance, "EDITMENU" ) ;
               HMENU popup = GetSubMenu( menu, 0 );
               POINT pos,pos1 ;
               ptr = (DWINFO*)GetWindowLong(hwnd,0) ;
               if (!SendMessage(ptr->dwHandle,EM_GETMODIFY,0,0))
                  EnableMenuItem(menu,IDM_SAVE,MF_GRAYED) ;
               if (uState != atBreakpoint) {
                  EnableMenuItem(menu,IDM_RUNTO,MF_GRAYED) ;
                  EnableMenuItem(menu,IDM_ADDWATCHINDIRECT,MF_GRAYED) ;
               }
  					GetCursorPos( &pos );
               pos1.x = pos.x ;
               pos1.y = pos.y ;
               ScreenToClient(ptr->dwHandle,&pos1) ;
               i = SendMessage(ptr->dwHandle,EM_CHARFROMPOS,0,(LPARAM)&pos1) & 0xffff;
               SendMessage(ptr->dwHandle,EM_SETSEL,i,i) ;
  					TrackPopupMenuEx( popup, TPM_BOTTOMALIGN | TPM_LEFTBUTTON,
                        pos.x, pos.y, hwndFrame, NULL );
  					DestroyMenu( menu );
         }
         return 0 ;
		case WM_SYSCOMMAND :
         if (wParam == SC_CLOSE)
            return SendMessage(hwnd,WM_COMMAND,IDM_CLOSE,0) ;
			break ;
      case WM_CHECKCHANGE:
         ptr = (DWINFO*)GetWindowLong(hwnd,0) ;
         if (FileTime(&time,ptr->dwName)) {
            if (time.dwHighDateTime != ptr->time.dwHighDateTime ||
               time.dwLowDateTime != ptr->time.dwLowDateTime) {
               if (ExtendedMessageBox("File has changed",MB_YESNO,"File %s has changed outside the editor.  Reload?", ptr->dwTitle) == IDYES)
                  LoadFile(hwnd, ptr) ;
               else
                  FileTime(&ptr->time,ptr->dwName) ;
            }
         }
         break ;
		case WM_COMMAND:
			switch(LOWORD(wParam)) {
            case IDM_CONTEXTHELP:
					ptr = (DWINFO*)GetWindowLong(hwnd,0) ;
               i = SendMessage(ptr->dwHandle,WM_COMMAND,wParam,lParam) ;
               break ;
				case IDM_GOTO:
               lParam = DialogBox(hInstance,"GOTODIALOG",hwnd,(DLGPROC)gotoProc) ;
				if (lParam == 0)
					break ;
				// fall through
            case IDM_SETLINE:
					ptr = (DWINFO*)GetWindowLong(hwnd,0) ;
               i = SendMessage(ptr->dwHandle,EM_LINEINDEX,lParam-1,0) ;
               SendMessage(ptr->dwHandle,EM_SETSEL,i,i) ;
               SendMessage(ptr->dwHandle,EM_SCROLLCARET,0,0) ;
					drawParams(ptr->dwHandle) ;
               InvalidateRect(hwnd,0,0) ;
               break ;
				case ID_REDRAWSTATUS:
					ptr = (DWINFO*)GetWindowLong(hwnd,0) ;
               drawParams(ptr->dwHandle) ;
               InvalidateRect(hwnd,0,0) ;
					break ;
				case ID_QUERYHASFILE:
					ptr = (DWINFO *)GetWindowLong(hwnd,0) ;
					ptr1 =(DWINFO *)lParam ;
					return !xstricmpz(ptr->dwName,ptr1->dwName) ;
				case ID_QUERYSAVE:
					ptr = (DWINFO *)GetWindowLong(hwnd,0) ;
               rv = SendMessage(ptr->dwHandle,EM_GETMODIFY,0,0) ;
               if (rv) {
                  return ExtendedMessageBox("File Has Changed",MB_YESNOCANCEL,"File %s has changed.  Do you wish to save it?",ptr->dwTitle) ;
               } else
                  return IDNO ;
				case IDM_SAVEAS:
dialog:
					ptr = (DWINFO*)GetWindowLong(hwnd,0) ;
               if (!SaveFileDialog(&ofn,ptr->dwName,hwnd,TRUE,szSourceFilter,"FILEDIR",0)) 
						break ;
					strcpy(ptr->dwTitle,ofn.lpstrFileTitle) ;
					strcpy(ptr->dwName,ofn.lpstrFile) ;
					SetWindowText(hwnd,ptr->dwTitle) ;
				case IDM_SAVE:
save:
					ptr = (DWINFO*)GetWindowLong(hwnd,0) ;
					if (ptr->dwName[0] == 0)
						goto dialog ;
               rv = SaveFile(hwnd,(char *)GetWindowLong(hwnd,0)) ;
               TagLinesAdjust(ptr->dwName,FALSE,FALSE) ;
               SendMessage(ptr->dwHandle,EM_SETMODIFY,0,0) ;
               return rv ;
					break ;
				case IDM_CLOSE:
               {
                  rv = SendMessage(hwnd,WM_COMMAND,ID_QUERYSAVE,0) ;
                  switch(rv) {
                     case IDYES:
                        if (SendMessage(hwnd,WM_COMMAND,IDM_SAVE,0))
                           SendMessage(hwnd,WM_CLOSE,0,0) ;
                        break ;
                     case IDNO:
                        ptr = (DWINFO*)GetWindowLong(hwnd,0) ;
                        TagLinesAdjust(ptr->dwName,TRUE,FALSE) ;
                        SendMessage(hwnd,WM_CLOSE,0,0) ;
                        break ;
                     case IDCANCEL:
                        break ;
                  }
                  return rv ;
               }
					break ;
				case IDM_UNDO:
               SendMessage(GetDlgItem(hwnd,ID_EDITCHILD),WM_UNDO,0,0) ;
					break ;
				case IDM_CUT:
               SendMessage(GetDlgItem(hwnd,ID_EDITCHILD),WM_CUT,0,0) ;
					break ;
				case IDM_COPY:
               SendMessage(GetDlgItem(hwnd,ID_EDITCHILD),WM_COPY,0,0) ;
					break ;
				case IDM_PASTE:
               SendMessage(GetDlgItem(hwnd,ID_EDITCHILD),WM_PASTE,0,0) ;
					break ;
				case IDM_SELECTALL:
               SendMessage(GetDlgItem(hwnd,ID_EDITCHILD),EM_SETSEL,0,-1) ;
					break ;
				case IDM_FIND:
               PopFindString(hwnd) ;
					break ;
				case IDM_REPLACE:
               PopReplaceString(hwnd) ;
					break ;
				case IDM_FINDNEXT:
					if (finding)
                  FindNextString(hwnd,&find,0,0) ;
					else
						ReplaceNextString(hwnd,&replace) ;
					break ;
            case IDM_TOUPPER:
               SendMessage(GetDlgItem(hwnd,ID_EDITCHILD),EM_TOUPPER,0,0) ;
               break ;
            case IDM_TOLOWER:
               SendMessage(GetDlgItem(hwnd,ID_EDITCHILD),EM_TOLOWER,0,0) ;
               break ;
				default:
					return DefMDIChildProc(hwnd,iMessage,wParam,lParam) ;
			}
			break ;
      case EM_CANUNDO:
         return SendMessage(GetDlgItem(hwnd,ID_EDITCHILD),EM_CANUNDO,0,0) ;
		case WM_SETCURSOR:
         drawParams(GetDlgItem(hwnd,ID_EDITCHILD)) ;
         GetClientRect(hwnd,&r) ;
         r.right = EDITOR_OFFSET - 3 ;
         InvalidateRect(hwnd,&r,0) ;
			break ;
      case WM_SETBREAKLINE:
         ptr = (DWINFO*)GetWindowLong(hwnd,0) ;
         win = 0 ;
         i = FALSE ;
         if (lParam == 0 ) {
            if (ptr->breakpointLine) {
               ptr->breakpointLine = 0 ;
               i = TRUE ;
            }
         } else {
            if (!xstricmpz((char *)wParam, ptr->dwName)) {
               win = hwnd ;
               ptr->breakpointLine = lParam ;
               i = TRUE ;
            } else
               if (ptr->breakpointLine) {
                  ptr->breakpointLine = 0 ;
                  i = TRUE ;
               }
         }
         if (i) {
            if (ptr->breakpointLine) {
//               i = SendMessage(ptr->dwHandle,EM_LINEINDEX,ptr->breakpointLine-1,0) ;
//               SendMessage(ptr->dwHandle,EM_SETSEL,i,i) ;
//               SendMessage(ptr->dwHandle,EM_SCROLLCARET,0,0) ;
               if (GetFocus() != hwndASM)
                  SetFocus(ptr->dwHandle) ;
            }
            GetClientRect(hwnd,&r) ;
            r.right = EDITOR_OFFSET - 3 ;
            InvalidateRect(hwnd,&r,0) ;
         }
         return win ;
		case WM_PAINT:
			GetClientRect(hwnd,&r) ;
			dc = BeginPaint(hwnd,&paint) ;
			hpen = CreatePen(PS_SOLID,1,0xcccccc),oldpen ;
			r.right = EDITOR_OFFSET-3;
			MoveToEx(dc, EDITOR_OFFSET-1,0,0) ;
			LineTo(dc,EDITOR_OFFSET-1, r.bottom) ;
			oldpen = SelectObject(dc,hpen) ;
			MoveToEx(dc,EDITOR_OFFSET-2,0,0) ;
			LineTo(dc,EDITOR_OFFSET-2,r.bottom) ;
			SelectObject(dc,oldpen) ;
			DeleteObject(hpen) ;
         PaintBreakpoints(hwnd, dc,&paint,&r) ;
			EndPaint(hwnd,&paint) ;
			return 0 ;
		case WM_CREATE:
//         maximized = TRUE ;
			ptr = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWINFO)) ;
         ptr->breakpointLine = 0 ;
			SetWindowLong(hwnd,0,(int)ptr) ;
			children[numberofdrawwindows++] = hwnd ;
			if (newInfo == (DWINFO *)-1) {
				SetWindowText(hwnd,szUntitled) ;
#ifdef XXXXX
			} else if (!newInfo) {
            if (OpenFileDialog(&ofn,0,hwnd,FALSE,FALSE, szSourceFilter,"FILEDIR",0)) {
					strcpy(ptr->dwTitle, ofn.lpstrFileTitle) ;
					SetWindowText(hwnd,ptr->dwTitle) ;
					strcpy(ptr->dwName,ofn.lpstrFile) ;
				} else {
               ExtendedMessageBox("File Open",0,"Could not open file %s",ptr->dwName) ;
					return -1 ;
				}
#endif
			} else {
					strcpy(ptr->dwTitle, newInfo->dwTitle) ;
					SetWindowText(hwnd,newInfo->dwTitle) ;
					strcpy(ptr->dwName,newInfo->dwName) ;
			}
         ptr->dwHandle = CreateWindowEx(0,"xedit",0,WS_CHILD + WS_CLIPSIBLINGS + WS_VISIBLE +
							WS_HSCROLL + WS_VSCROLL + 
							ES_LEFT + ES_MULTILINE + ES_NOHIDESEL +
							ES_AUTOVSCROLL + ES_AUTOHSCROLL,
                     EDITOR_OFFSET,0,0,0,
                     hwnd,(HMENU)ID_EDITCHILD,hInstance,0);
         if (stristr(ptr->dwName,".c") != ptr->dwName + strlen(ptr->dwName)-2 &&
               stristr(ptr->dwName,".cpp") != ptr->dwName + strlen(ptr->dwName)-4 &&
               stristr(ptr->dwName,".h") != ptr->dwName + strlen(ptr->dwName)-2)
            SendMessage(ptr->dwHandle,EM_NOCOLORIZE,0,0) ;
         if (ptr->dwName[0])
            LoadFile(hwnd,ptr) ;
			if (newInfo != (DWINFO *)-1) {
            InsertMRU(ptr,0) ;
            MRUToMenu(0) ;
			}
         if (newInfo && newInfo != (DWINFO *)-1 && newInfo->dwLineNo != -1) {
            PostMessage(hwnd,WM_COMMAND,IDM_SETLINE,newInfo->dwLineNo) ;
				newInfo->dwLineNo = -1 ;
         }
         PostMessage(hwndSourceTab,WM_RESETTABS,0,0) ;
         return 0 ;
				
		case WM_CLOSE:
         ptr = (DWINFO*)GetWindowLong(hwnd,0) ;
         eraseParams(ptr->dwHandle) ;
			break ;
		case WM_DESTROY:
			for (i=0 ; i < numberofdrawwindows; i++)
				if (children[i] == hwnd)
					break ;
         if (i < numberofdrawwindows-1)
            memcpy(children+i,children+i+1,(numberofdrawwindows-i-1) * sizeof(HWND)) ;
         if (--numberofdrawwindows == 0 && IsWindow(hwndFind)) {
            DestroyWindow(hwndFind) ;
            hwndFind = 0 ;
         }
         SendMessage(hwndSourceTab,WM_RESETTABS,0,0) ;
			HeapFree(GetProcessHeap(),0,(void *)GetWindowLong(hwnd,0)) ;
         PostMessage(hwndFrame,WM_REDRAWTOOLBAR,0,0) ;
			break ;
		case WM_SIZE:       
         MoveWindow(GetDlgItem(hwnd,ID_EDITCHILD),EDITOR_OFFSET,0,(lParam & 65535)-EDITOR_OFFSET, lParam >> 16,1) ;
			break ;
		case WM_SETFOCUS:
         SetFocus(GetDlgItem(hwnd,ID_EDITCHILD)) ;
			drawParams(GetDlgItem(hwnd,ID_EDITCHILD)) ;
         InvalidateRect(hwnd,0,0) ;
         PostMessage(hwndFrame,WM_REDRAWTOOLBAR,0,0) ;
         for (i=0; i < numberofdrawwindows; i++)
            if (hwnd == children[i]) {
               PostMessage(hwndSourceTab, WM_SETACTIVETAB,0,i) ;
               break ;
            }
			return 0 ;
      case WM_KILLFOCUS:
         SendMessage(GetDlgItem(hwnd,ID_EDITCHILD),iMessage,wParam,lParam) ;
         return 0 ;
		case WM_INITMENUPOPUP:
         SendMessage(GetDlgItem(hwnd,ID_EDITCHILD),EM_GETSEL,(WPARAM)&startpos, (LPARAM)&endpos) ;
			flag = startpos < endpos ;
			EnableMenuItem(hMenuMain,IDM_CUT,flag) ;
			EnableMenuItem(hMenuMain,IDM_COPY,flag) ;
			EnableMenuItem(hMenuMain,IDM_PASTE,1) ;
         EnableMenuItem(hMenuMain,IDM_UNDO, SendMessage(GetDlgItem(hwnd,ID_EDITCHILD),EM_CANUNDO,0,0)) ;
         EnableMenuItem(hMenuMain,IDM_BROWSE,flag) ;
         //EnableMenuItem(hMenuMain,IDM_BROWSEBACK,flag) ;
         EnableMenuItem(hMenuMain,IDM_BOOKMARK,flag) ;
         //EnableMenuItem(hMenuMain,IDM_NEXTBOOKMARK,flag) ;
         //EnableMenuItem(hMenuMain,IDM_PREVBOOKMARK,flag) ;
			return 0 ;
      case WM_WORDUNDERCURSOR:  
         ptr = (DWINFO*)GetWindowLong(hwnd,0) ;
         return SendMessage(ptr->dwHandle,iMessage,wParam,lParam) ;
      case WM_FILETITLE:
         ptr = (DWINFO*)GetWindowLong(hwnd,0) ;
         return ptr->dwTitle ;
      case WM_FILENAME:
         ptr = (DWINFO*)GetWindowLong(hwnd,0) ;
         return ptr->dwName ;
		default: 
			if (iMessage == iFindMessage) {
            HWND edit ;
				if (finding) {
               edit = GetDlgItem(hwndFind,1152) ;
               SendMessage(edit,WM_SAVEHISTORY,0,0) ;
					if (find.Flags & FR_FINDNEXT)
                  FindNextString(hwnd,&find,0,0) ;
//               if (find.Flags & FR_DIALOGTERM)
//                  hwndFind = 0 ;
				} else {
               edit = GetDlgItem(hwndFind,1152) ;
               SendMessage(edit,WM_SAVEHISTORY,0,0) ;
               edit = GetDlgItem(hwndFind,1153) ;
               SendMessage(edit,WM_SAVEHISTORY,0,0) ;
					if (replace.Flags & (FR_FINDNEXT | FR_REPLACE | FR_REPLACEALL))
						ReplaceNextString(hwnd,&replace );
//               if (replace.Flags & FR_DIALOGTERM)
//                  hwndFind = 0 ;
				}
			}
			break ;
	}
   return DefMDIChildProc(hwnd,iMessage,wParam,lParam) ;
}
void RegisterDrawWindow(void)
{
		WNDCLASS wc ;
      memset(&wc,0,sizeof(wc)) ;
      wc.style = 0;
		wc.lpfnWndProc = &DrawProc ;
		wc.cbClsExtra = 0;
		wc.cbWndExtra = sizeof(void *) ;
		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 = szDrawClassName ;
      pcBitmap = LoadBitmap(hInstance, "ID_PCBMP") ;
      stoppcBitmap = LoadBitmap(hInstance, "ID_STOPPCBMP") ;
      tagBmps[TAG_BP] = LoadBitmap(hInstance, "ID_STOPBMP") ;
      tagBmps[TAG_FIF1] = LoadBitmap(hInstance, "ID_FIF1BMP") ;
      tagBmps[TAG_FIF2] = LoadBitmap(hInstance, "ID_FIF2BMP") ;
      tagBmps[TAG_BOOKMARK] = LoadBitmap(hInstance, "ID_BOOKMARKBMP") ;
      ChangeBitmapColor(pcBitmap,0xffffff,GetSysColor(COLOR_3DFACE)) ;
      ChangeBitmapColor(stoppcBitmap,0xffffff,GetSysColor(COLOR_3DFACE)) ;
      ChangeBitmapColor(tagBmps[TAG_BP],0,GetSysColor(COLOR_3DFACE)) ;
      ChangeBitmapColor(tagBmps[TAG_FIF1],0,GetSysColor(COLOR_3DFACE)) ;
      ChangeBitmapColor(tagBmps[TAG_FIF2],0,GetSysColor(COLOR_3DFACE)) ;
      ChangeBitmapColor(tagBmps[TAG_BOOKMARK],0,GetSysColor(COLOR_3DFACE)) ;
		RegisterClass(&wc) ;
      findflags = ProfileToInt("FindFlags",12) ;
      replaceflags = ProfileToInt("ReplaceFlags",4) ;
}
HWND openfile(DWINFO *newInfo)
{
	MDICREATESTRUCT mc ;
	HWND rv ;
   BOOL maximized ;
   SendMessage(hwndClient, WM_MDIGETACTIVE,0,(LPARAM)&maximized) ;
   memset(&mc,0,sizeof(mc)) ;
	mc.szClass = szDrawClassName ;
	mc.szTitle = szUntitled ;
	mc.hOwner = hInstance ;
	mc.x = childxpos ;
	mc.y = childypos ;
	mc.cx = 0;
	mc.cy = 0;
   mc.style = WS_CHILD | WS_VISIBLE | WS_OVERLAPPEDWINDOW |  WS_SYSMENU | WS_SIZEBOX|WS_MINIMIZEBOX | WS_MAXIMIZEBOX | (maximized ? WS_MAXIMIZE : 0);
	mc.lParam = 0 ;
   rv = (HWND) SendMessage(hwndClient,WM_MDICREATE,0,(LPARAM)&mc) ;
	childxpos += 20 ;
	childypos += 20 ;
	if (childxpos > 120)
      childxpos = childypos = 0 ;
	return rv ;
}
HWND CreateDrawWindow(DWINFO *baseinfo)
{
	int i ;
   DWINFO temp ;
	OPENFILENAME ofn ;
	if (baseinfo && baseinfo != (DWINFO *)-1)
		for (i=0; i < MAX_CHILDREN; i++)
         if (children[i] && SendMessage(children[i],WM_COMMAND,ID_QUERYHASFILE,(LPARAM)baseinfo)) {
				BringWindowToTop(children[i]) ;
				SetFocus(children[i]) ;
				if (baseinfo->dwLineNo != -1)
               PostMessage(children[i],WM_COMMAND,IDM_SETLINE,baseinfo->dwLineNo) ;
				return children[i] ;
			}

	if (numberofdrawwindows >= MAX_CHILDREN) {
		ExtendedMessageBox("Error",0,"Too many edit windows open") ;
		return 0 ;
	}

	newInfo = baseinfo ;
   if (!newInfo) {
      newInfo = &temp ;
      newInfo->dwLineNo = -1 ;
            if (OpenFileDialog(&ofn,0,0,FALSE,TRUE, szSourceFilter,"FILEDIR",0)) {
               char *q = ofn.lpstrFile, path[256] ;
               strcpy(path,ofn.lpstrFile) ;
               q += strlen(q) + 1 ;
               if (!*q) {
                  strcpy(newInfo->dwTitle, ofn.lpstrFileTitle) ;
                  strcpy(newInfo->dwName,ofn.lpstrFile) ;
               } else {
                  while (*q) {
                     strcpy(newInfo->dwTitle,q) ;
                     sprintf(newInfo->dwName,"%s\\%s",path,q) ;
                     openfile(newInfo) ;
                     q += strlen(q) + 1 ;
                  }
                  return 0 ;
               }
				} else {
               ExtendedMessageBox("File Open",0,"Could not open file %s",newInfo->dwName) ;
               return 0 ;
				}
   }
   return openfile(newInfo) ;
}