 /*  R : A Computer Langage for Statistical Data Analysis
 *  Copyright (C) 1995  Robert Gentleman and Ross Ihaka
 *
 *  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., 675 Mass Ave, Cambridge, MA 02139, USA.
 */


#include "wincons.h"
#include <commdlg.h>

#define MAX_STRING_LEN   256

static char szFindText [MAX_STRING_LEN] ;
static char szReplText [MAX_STRING_LEN] ;

static char szFilter[RBuffLen + 2];
static char szImgFilter[] = "R Image File(*.RMG)|*.rmg";
static char szOpenFilter[] = "Text Files (*.TXT)|*.txt|All Files(*.*)|*.*";
static char szDataFilter[] = "Data Files (*.DAT)|*.dat|All Files(*.*)|*.*";
static char szSysDatFilter[] = "R Data Files (*.R)|*.R| Tables (*.tab)|*.tab| All Files(*.*)|*.*";
static char szDirName[RBuffLen];
extern char RFName[RBuffLen];

OPENFILENAME ofn;

static void ofninit()
{
        ofn.lStructSize = sizeof(OPENFILENAME);
        ofn.hwndOwner = NULL;
        ofn.hInstance = NULL;
        ofn.lpstrFilter = NULL;
        ofn.lpstrCustomFilter = NULL;
        ofn.nMaxCustFilter = 0;
        ofn.nFilterIndex = 0;
        ofn.lpstrFile = NULL;
        ofn.nMaxFile = 0;
        ofn.lpstrFileTitle = 0;
        ofn.nMaxFileTitle = 0;
        ofn.lpstrTitle = NULL;
        ofn.nFileOffset = 0;
        ofn.nFileExtension = 0;
        ofn.lpstrInitialDir = NULL;
        ofn.Flags = 0;
        ofn.nFileOffset = 0;
        ofn.nFileExtension = 0;
        ofn.lpstrDefExt = NULL;
        ofn.lCustData = 0L;
        ofn.lpfnHook = NULL;
        ofn.lpTemplateName = NULL;
}

/* which = 1 ==> Open
   which = 2 ==> Load
   which = 3 ==> read.table
   which = 4 ==> open a system data file
   */
   

int Win_ROpenDlg(HWND hwnd, int which)
{
        int i, n;
        char title[512];

        switch (which) {
            case 1:
                strcpy(szFilter, szImgFilter);
                sprintf(title, "R Open File");
                break;
            case 2:
                strcpy(szFilter, szOpenFilter);
                sprintf(title, "R Load File");
                break;
            case 3:
                strcpy(szFilter, szOpenFilter);
                sprintf(title, "R read.table");
                break;
            case 4:
                strcpy(szFilter, szOpenFilter);
                sprintf(title, "R read file");
                break;
        }

        n = strlen(szFilter);
        for (i = 0; i < n; i++)
                if (szFilter[i] == '|')
                        szFilter[i] = '\0';
        szFilter[n] = '\0';
        szFilter[n + 1] = '\0';

        if (! GetCurrentDirectory(sizeof(szDirName), szDirName))
                return 0;

        ofninit();
        
        
        ofn.lpstrFilter = szFilter;
        ofn.nFilterIndex = 2;
        ofn.lpstrFile = RFName;
        ofn.nMaxFile = RBuffLen;
        ofn.lpstrInitialDir = szDirName;
        ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
        ofn.lpstrTitle = title;

        return (int) GetOpenFileName(&ofn);
}

int Win_RSaveDlg(HWND hwnd)
{
        int i, n;

        strcpy(szFilter, szImgFilter);

        n = strlen(szFilter);
        for (i = 0; i < n; i++)
                if (szFilter[i] == '|')
                        szFilter[i] = '\0';
        szFilter[n] = '\0';
        szFilter[n + 1] = '\0';

        if (! GetCurrentDirectory(sizeof(szDirName), szDirName))
                return 0;

        ofninit();
        
       
        ofn.lpstrFilter = szFilter;
        ofn.nFilterIndex = 1;
        ofn.lpstrFile = RFName;
        ofn.nMaxFile = RBuffLen;
        ofn.lpstrInitialDir = szDirName;
        ofn.Flags = OFN_OVERWRITEPROMPT;
        ofn.lpstrTitle = "R Save Image";

        return (int) GetSaveFileName(&ofn);
}

int Win_RDataDlg(HWND hwnd, char* datadirname)
{
        int i, n;

        strcpy(szFilter, szDataFilter);

        n = strlen(szFilter);
        for (i = 0; i < n; i++)
                if (szFilter[i] == '|')
                        szFilter[i] = '\0';
        szFilter[n] = '\0';
        szFilter[n + 1] = '\0';

        if( strlen(datadirname) == 0 )
                if (! GetCurrentDirectory(sizeof(szDirName), szDirName))
                        return 0;
        else
                strcpy(szDirName,datadirname);

        ofninit();
        
       
        ofn.lpstrFilter = szFilter;
        ofn.nFilterIndex = 1;
        ofn.lpstrFile = RFName;
        ofn.nMaxFile = RBuffLen;
        ofn.lpstrInitialDir = szDirName;
        ofn.Flags = OFN_OVERWRITEPROMPT;
        ofn.lpstrTitle = "R Read Data";

        return (int) GetSaveFileName(&ofn);
}


HWND R_FindDlg (HWND hwnd)
     {
     static FINDREPLACE fr ;       // must be static for modeless dialog!!!

     fr.lStructSize      = sizeof (FINDREPLACE) ;
     fr.hwndOwner        = hwnd ;
     fr.hInstance        = NULL ;
     fr.Flags            = FR_HIDEUPDOWN | FR_HIDEMATCHCASE | FR_HIDEWHOLEWORD ;
     fr.lpstrFindWhat    = szFindText ;
     fr.lpstrReplaceWith = NULL ;
     fr.wFindWhatLen     = sizeof (szFindText) ;
     fr.wReplaceWithLen  = 0 ;
     fr.lCustData        = 0 ;
     fr.lpfnHook         = NULL ;
     fr.lpTemplateName   = NULL ;

     return FindText(&fr) ;
     }

HWND R_ReplaceDlg (HWND hwnd)
     {
     static FINDREPLACE fr ;       // must be static for modeless dialog!!!

     fr.lStructSize      = sizeof (FINDREPLACE) ;
     fr.hwndOwner        = hwnd ;
     fr.hInstance        = NULL ;
     fr.Flags            = FR_HIDEUPDOWN | FR_HIDEMATCHCASE | FR_HIDEWHOLEWORD ;
     fr.lpstrFindWhat    = szFindText ;
     fr.lpstrReplaceWith = szReplText ;
     fr.wFindWhatLen     = sizeof (szFindText) ;
     fr.wReplaceWithLen  = sizeof (szReplText) ;
     fr.lCustData        = 0 ;
     fr.lpfnHook         = NULL ;
     fr.lpTemplateName   = NULL ;

     return ReplaceText(&fr) ;
     }
static int GetTextHt(HWND edit)
{
	HFONT hf, hf1;
	HDC dc;
	TEXTMETRIC tm;

	hf = SendMessage(edit, WM_GETFONT, 0, 0);
	if( hf != NULL ) {
		dc = GetWindowDC(edit);
		hf1 = SelectObject(dc, hf);
		GetTextMetrics(dc, &tm);
		SelectObject(dc, hf1); // restore the old font
		ReleaseDC(edit, dc);
		return tm.tmHeight;
	}
	return 0;
}

static int GetVisLines(HWND edit, int txtht)
{
	RECT r;

	SendMessage(edit, EM_GETRECT, (LPARAM) NULL, (WPARAM) &r);
	return r.bottom/txtht;
}

static int nscroll(HWND edit, int vislines)
{
	int first, last;

	first = SendMessage(edit, EM_GETFIRSTVISIBLELINE, 0, 0);
	last = SendMessage(edit, EM_GETLINECOUNT, 0, 0);
	return 0;
}

BOOL intersect(RECT r1, RECT r2)
{
	int i=0, j=0;

	if( r1.top <= r2.top ) {
		if( r1.bottom >= r2.top )
			i=1;
	}
	else if(r2.bottom > r1.top)
		i=1;

	if( r1.left <= r2.left ) {
		if( r1.right >= r2.left )
			j=1;
	}
	else if( r1.left < r2.right)
		j=1;

	if( i*j )
		return TRUE;
	return FALSE;
}

BOOL R_FindText (HWND hwndEdit, HWND dlg, int *piSearchOffset, LPFINDREPLACE pfr)
     {
     int   iLength, iPos, txtht, first, nline;
	 int vl, bot, dlght;
     PSTR  pstrDoc, pstrPos ;
	 RECT r1, r2;

               // Read in the edit document

     iLength = GetWindowTextLength (hwndEdit) ;

     if (NULL == (pstrDoc = (PSTR) malloc (iLength + 1)))
          return FALSE ;

     GetWindowText (hwndEdit, pstrDoc, iLength + 1) ;

               // Search the document for the find string

     pstrPos = strstr (pstrDoc + *piSearchOffset, pfr->lpstrFindWhat) ;
     free (pstrDoc) ;

               // Return an error code if the string cannot be found

     if (pstrPos == NULL)
          return FALSE ;

               // Find the position in the document and the new start offset

     iPos = pstrPos - pstrDoc ;
     *piSearchOffset = iPos + strlen (pfr->lpstrFindWhat);

     SendMessage (hwndEdit, EM_SETSEL, iPos, *piSearchOffset);
     SendMessage (hwndEdit, EM_SCROLLCARET, 0, 0);

	 //find out where the dialog window is and if it obscures
	 //the found text we need to scroll

	 GetWindowRect(dlg, &r1);
	 GetWindowRect(hwndEdit, &r2);
	 if( intersect(r1,r2) ) {
	 //SendMessage(hwndEdit, EM_GETRECT, (LPARAM) NULL, (WPARAM) &r2);
		first = SendMessage(hwndEdit, EM_GETFIRSTVISIBLELINE, 0, 0);
		txtht = GetTextHt(hwndEdit);
		vl = GetVisLines(hwndEdit, txtht);
		nline = SendMessage(hwndEdit, EM_LINEFROMCHAR, (WPARAM) iPos, 0);		
		if( nline >= first && nline <= first+vl) { // its visible
			bot = r2.bottom-txtht*(vl+first-nline);
			r2.bottom=bot;
			r2.top=bot-12;
			if( intersect(r2, r1) ) { // move the edit window
				dlght=r1.bottom-r1.top;
				if( dlght < r2.top )
					MoveWindow(dlg, r1.left, r2.top-10-dlght,
						r1.right-r1.left, dlght, TRUE);
				else 
					MoveWindow(dlg, r1.left, r2.bottom+10,
					    r1.right-r1.left, dlght, TRUE);
			}
		}
	 }


               // Select the found text
	 SetFocus(hwndEdit);

     return TRUE ;
     }

BOOL R_FindNextText (HWND hwndEdit, HWND dlg, int *piSearchOffset)
     {
     FINDREPLACE fr ;

     fr.lpstrFindWhat = szFindText ;

     return R_FindText (hwndEdit, dlg, piSearchOffset, &fr) ;
     }

BOOL R_ReplaceText (HWND hwndEdit, HWND dlg, int *piSearchOffset, LPFINDREPLACE pfr)
     {
               // Find the text

     if (!R_FindText (hwndEdit, dlg, piSearchOffset, pfr))
          return FALSE ;

               // Replace it

     SendMessage (hwndEdit, EM_REPLACESEL, 0, (LPARAM) pfr->lpstrReplaceWith) ;

     return TRUE ;
     }
BOOL R_ValidFind(void)
{
	return *szFindText != '\0';
}