/***************************************************************************
 *									   *
 *  MODULE	: MpFile.c						   *
 *									   *
 *  PURPOSE	: Contains the code for File i/o for Multipad.		   *
 *									   *
 *  FUNCTIONS	:							   *
 *		  AddFile()	   - Creates a new MDI window. Given an    *
 *				     option, it loads a file into it.	   *
 *									   *
 *		  LoadFile ()	   - Loads a file into the MDI window.	   *
 *									   *
 *		  ReadFile ()	   - In response to File/Open menu,	   *
 *				     calls AddFile()			   *
 *									   *
 *		  SaveFile ()	   - Saves contents of an edit control to  *
 *				     a file.				   *
 *									   *
 *		  SetSavefrom()    - Formats the "Save 'file' to" string.  *
 *									   *
 *		  SaveAsDlgProc()  - Dialog function for File/SaveAs.	   *
 *									   *
 *		  ChangeFile()	   - Calls File/SaveAs dialog.		   *
 *									   *
 ***************************************************************************/
#include "multipad.h"

VOID NEAR PASCAL GetFileName(PSTR);
int FAR PASCAL DialogBoxParam(HANDLE,LPSTR,HWND,FARPROC,LONG);

/****************************************************************************
 *									    *
 *  FUNCTION   : AddFile (lpName)					    *
 *									    *
 *  PURPOSE    : Creates a new MDI window. If the lpName parameter is not   *
 *		 NULL, it loads a file into the window. 		    *
 *									    *
 *  RETURNS    : HWND  - A handle to the new window.			    *
 *									    *
 ****************************************************************************/

HWND FAR PASCAL AddFile ( lpName )
LPSTR lpName;
{
    HWND hwnd;

    char	    sz[160];
    MDICREATESTRUCT mcs;

    if (!lpName){
	/* If the lpName parameter is NULL, load the "Untitled" string
	 * from STRINGTABLE and set the title field of the MDI CreateStruct.
	 */
	LoadString (hInst, IDS_UNTITLED, sz, sizeof(sz));
	mcs.szTitle = (LPSTR)sz;
    }
    else{
	/* Title the window with the supplied filename */
	AnsiUpper (lpName);
	mcs.szTitle = lpName;
    }

    mcs.szClass = szChild;
    mcs.hOwner	= hInst;

    /* Use the default size for the window */
    mcs.x = mcs.cx = CW_USEDEFAULT;
    mcs.y = mcs.cy = CW_USEDEFAULT;

    /* Set the style DWORD of the window to default */
    mcs.style = styleDefault;

    /* tell the MDI Client to create the child */
    hwnd = (WORD)SendMessage (hwndMDIClient,
			      WM_MDICREATE,
			      0,
			      (LONG)(LPMDICREATESTRUCT)&mcs);

    /* Did we get a file? Read it into the window */
    if (lpName)
	LoadFile (hwnd, lpName);

    return hwnd;

}

/****************************************************************************
 *									    *
 *  FUNCTION   : LoadFile (lpName)					    *
 *									    *
 *  PURPOSE    : Given the handle to a MDI window and a filename, reads the *
 *		 file into the window's edit control child.                 *
 *									    *
 *  RETURNS    : TRUE  - If file is sucessfully loaded. 		    *
 *		 FALSE - Otherwise.					    *
 *									    *
 ****************************************************************************/
int FAR PASCAL LoadFile (hwnd, lpName)
HWND hwnd;
LPSTR lpName;
{
    WORD   wLength;
    HANDLE hT;
    LPSTR  lpB;
    HWND   hwndEdit;
    int    fh;

    hwndEdit = GetWindowWord (hwnd, GWW_HWNDEDIT);

    /* The file has a title, so mark the appropriate flag. */
    SetWindowWord(hwnd, GWW_UNTITLED, 0);

    fh = _lopen (lpName, 0);

    /* Make sure file has been opened correctly */
    if ( fh < 0 )
	goto error;

    /* Find the length of the file */
    wLength = (WORD)_llseek (fh, 0L, 2);
    _llseek (fh, 0L, 0);

    /* Attempt to reallocate the edit control's buffer to the file size */
    hT = (HANDLE)SendMessage (hwndEdit, EM_GETHANDLE, 0, 0L);
    if (!LocalReAlloc (hT, wLength+1, LHND)){
	LocalUnlock (hT);
	_lclose (fh);
	goto error;
    }

    /* read the file into the buffer */
    if (wLength != _lread (fh, (lpB = (LPSTR)LocalLock (hT)), wLength))
	MPError (hwnd, MB_OK|MB_ICONHAND, IDS_CANTREAD, lpName);

    /* Zero terminate the edit buffer */
    lpB [wLength] = 0;
    LocalUnlock (hT);

    SendMessage (hwndEdit, EM_SETHANDLE, hT, 0L);
    _lclose (fh);

    return TRUE;

    /* Report the error and quit */
error:
    MPError(hwnd,MB_OK|MB_ICONHAND,IDS_CANTOPEN,lpName);
    return FALSE;

}

/****************************************************************************
 *									    *
 *  FUNCTION   : ReadFile (hwnd)					    *
 *									    *
 *  PURPOSE    : Called in response to a File/Open menu selection. It calls *
 *		 AddFile () to load the file into the control.		    *
 *									    *
 ****************************************************************************/
VOID FAR PASCAL ReadFile( hwnd )
HWND hwnd;
{
    char szFile[128];

    GetFileName (szFile);
    if ( *szFile )
	AddFile (szFile);

}
/****************************************************************************
 *									    *
 *  FUNCTION   : SaveFile (hwnd)					    *
 *									    *
 *  PURPOSE    : Saves contents of current edit control to disk.	    *
 *									    *
 ****************************************************************************/
VOID FAR PASCAL SaveFile( hwnd )

HWND hwnd;
{
    HANDLE   hT;
    LPSTR    lpT;
    char     szFile[64];
    WORD     cch;
    int      fh;
    OFSTRUCT of;
    HWND     hwndEdit;

    hwndEdit = GetWindowWord ( hwnd, GWW_HWNDEDIT);
    GetWindowText (hwnd, szFile, sizeof(szFile));

    /* If there is no extension (control is 'Untitled') add .TXT as extension */
    for (cch = FALSE, lpT = szFile; *lpT; lpT++)
	switch (*lpT){
	    case '.':
		 cch = TRUE;
		 break;

	    case '\\':
	    case ':' :
		 cch = FALSE;
		 break;
	}
    if (!cch)
	LoadString (hInst, IDS_ADDEXT, lpT, lpT - (LPSTR)szFile);

    fh = OpenFile (szFile, &of, OF_WRITE | OF_CREATE);

    /* If file could not be opened, quit */
    if (fh < 0){
	MPError (hwnd, MB_OK | MB_ICONHAND, IDS_CANTCREATE, (LPSTR)szFile);
	return;
    }

    /* Find out the length of the text in the edit control */
    cch = GetWindowTextLength (hwndEdit);

    /* Obtain a handle to the text buffer */
    hT	= (HANDLE)SendMessage (hwndEdit, EM_GETHANDLE, 0, 0L);
    lpT = (LPSTR)LocalLock (hT);

    /* Write out the contents of the buffer to the file. */
    if (cch != _lwrite (fh, lpT, cch))
	MPError (hwnd, MB_OK | MB_ICONHAND, IDS_CANTWRITE, (LPSTR)szFile);

    /* Clean up */
    LocalUnlock (hT);
    SendMessage (hwndEdit, EM_SETHANDLE, hT, 0L);

    _lclose (fh);

    return;
}
/****************************************************************************
 *									    *
 *  FUNCTION   : SetSaveFrom () 					    *
 *									    *
 *  PURPOSE    : Formats the "Save 'file' to .." string.		    *
 *									    *
 ****************************************************************************/

VOID NEAR PASCAL SetSaveFrom ( hwnd , psz)
HWND hwnd;
PSTR psz;
{
    char szFmt[32];
    char szText[160];

    /* The text string in the .RC file contains the format string... */
    GetDlgItemText( hwnd, IDD_SAVEFROM, szFmt, sizeof(szFmt));

    /* NOTE: this (LPSTR) cast MUST be here... wsprintf() is a cdecl
     * (C calling conventions) function with varying args... there is
     * no way for the compiler to know that all strings must be LPSTR's
     * and do the conversion, so we have to be careful about wsprintf()'s.
     */
    wsprintf ( szText, szFmt, (LPSTR)psz);

    /* set the text in the static control */
    SetDlgItemText (hwnd, IDD_SAVEFROM, szText);
}

/****************************************************************************
 *									    *
 *  FUNCTION   : SaveAsDlgProc(hwnd, message, wParam, lParam)		    *
 *									    *
 *  PURPOSE    : Dialog function File/SaveAs. It waits for a filename, and  *
 *		 then calls SaveFile or cancels the operation.		    *
 *									    *
 ****************************************************************************/
BOOL FAR PASCAL SaveAsDlgProc( hwnd, message, wParam, lParam)
HWND hwnd;
WORD message;
WORD wParam;
LONG lParam;
{
    char   sz[64];
    char   *pch;
    BOOL   fExt;
    HWND   hwndSave;

    switch (message){

	case WM_INITDIALOG:

	    /* Identify the window whose contents we're saving */
	    hwndSave = LOWORD (lParam);

	    /* Set it's name in the property list */
	    SetProp (hwnd, PROP_FILENAME, hwndSave);

	    GetWindowText (hwndSave, sz, sizeof(sz));

	    /* Set the save from string... */
	    SetSaveFrom (hwnd,sz);

	    /* Generate a filename complete with extension */
	    AnsiUpper (sz);
	    for (fExt = FALSE, pch = sz; *pch; pch++)
		if (*pch == '.')
		    fExt = TRUE;
		else if (*pch == '\\')
		    fExt = FALSE;
	    if (!fExt)
		LoadString (hInst, IDS_ADDEXT, (LPSTR)pch, pch - sz);

	    /* Display the filename in the edit control */
	    SetDlgItemText (hwnd, IDD_SAVETO, sz);

	    /* Select the entire range of text */
	    SendDlgItemMessage (hwnd, IDD_SAVETO, EM_SETSEL, 0, MAKELONG (0,100));

	    DlgDirList (hwnd, "*.*", IDD_DIRS, IDD_PATH, ATTR_DIRS);

	    /* enable OK butto iff edit control is nonempty */
	    if (!*sz)
		EnableWindow (GetDlgItem (hwnd, IDOK), FALSE);
	    break;

	case WM_COMMAND:
	    switch (wParam){
		case IDCANCEL:
		    /* Abort operation */
		    EndDialog(hwnd,1);
		    break;

		case IDOK:
		   /*  Just change the title of the MDI child. The calling
		    *  function of ChangeFile(), which uses the title text
		    *  for the filename, will do the actual save.
		    */
		    hwndSave = GetProp (hwnd, PROP_FILENAME);
		    GetDlgItemText (hwnd, IDD_SAVETO, sz, sizeof(sz));
		    AnsiUpper ((LPSTR)sz);
		    SetWindowText (hwndSave, sz);
		    EndDialog (hwnd, 0);
		    break;

		case IDD_SAVETO:
		   /* If the edit control changes, check to see if its empty.
		    * enable OK if it contains something
		    */
		    if (HIWORD (lParam) != EN_CHANGE)
			return FALSE;
		    EnableWindow (GetDlgItem (hwnd, IDOK),
			(WORD) SendDlgItemMessage (hwnd,
						   IDD_SAVETO,
						   WM_GETTEXTLENGTH,
						   0,
						   0L));
		    break;

		case IDD_DIRS:
		    if (HIWORD(lParam)==LBN_DBLCLK){
			char szT[64];

			DlgDirSelect ( hwnd, szT, IDD_DIRS);
			lstrcat ( szT, "*.*");
			DlgDirList (hwnd, szT, IDD_DIRS, IDD_PATH, ATTR_DIRS);
			break;
		    }
		    return FALSE;

		default:
		    return FALSE;
	    }

	default:
	    return FALSE;
    }
    return TRUE;
}
/****************************************************************************
 *									    *
 *  FUNCTION   : ChangeFile (hwnd)					    *
 *									    *
 *  PURPOSE    : Invokes the File/SaveAs dialog.			    *
 *									    *
 *  RETURNS    : TRUE  - if user selected OK or NO.			    *
 *		 FALSE - otherwise.					    *
 *									    *
 ****************************************************************************/
BOOL FAR PASCAL ChangeFile (hwnd)
HWND hwnd;
{
    FARPROC lpfn;
    int     i;

    lpfn = MakeProcInstance (SaveAsDlgProc, hInst);
    i = DialogBoxParam (hInst, IDD_SAVEAS, hwnd, lpfn, MAKELONG (hwnd, 0));
    FreeProcInstance (lpfn);
    if (!i)
	SetWindowWord (hwnd, GWW_UNTITLED, 0);
    return !i;
}
