/*
 * This file is part of the M-Edit program (Copyright 1996 by Vincenzo Morello)
 * Permission to use is hereby granted for any purpose.
 *
 * Contains file handling and utility callbacks.
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>

#if defined __TURBOC__ || defined _MSC_VER || defined __WATCOMC__
#include <io.h>
#ifndef R_OK
#define R_OK    04
#endif
#else
#include <unistd.h>
#endif

#include "mgui.h"
#include "medit.h"
#include "me.h"

void LoadPrefs(void);
void SetWindowOptions(MOBJECT shell);

/*
 * This array holds open windows OBJECT id
 */
MOBJECT windows[MAX_N_WINDOW];

/*
 * This string points to the pathname of the configuration file
 */
char pref_fname[MAXPATHLEN+1];

#ifdef WATC_MGUI

void mktemp(char *fname)
{
}

#endif

/*
 * Free an undo item
 */
static void FreeUndo(UNDO_DATA *pud)
{
	if (pud->oldtext)
		free(pud->oldtext);
	if (pud->newtext)
		free(pud->newtext);
	free(pud);
}

/*
 * Free all queued undo items for a window
 */
static void FreeUndoList(FILE_DATA *pfd)
{
	UNDO_DATA       *pud, *tmp;

	pud = pfd->first_undo;
	while (pud) {
		tmp = pud;
		pud = pud->next;
		FreeUndo(tmp);
	}
	pfd->first_undo = NULL;
	pfd->curr_undo = NULL;
	pfd->undo_level = 0;
}

/*
 * Read a file and ruturn the stream pointer and read-only status
 */
static char *LoadFile(char *filename, int *ro)
{
	FILE            *fp;
	char            str[256];
	char            *buff;
	struct stat     sb;
	int             nread;

	if (stat(filename, &sb) == -1) {
		sprintf(str, "Error accessing file:\n%s", filename);
		MMessageDialog("Error", str, " Ok ", NULL);
		return NULL;
	}
	if (sb.st_size > (long)INT_MAX) {
		MMessageDialog("Sorry", "File is too large !", " Ok ", NULL);
		return NULL;
	}
	if ((fp=fopen(filename, "r+")) == NULL) {
		if ((fp=fopen(filename, "r")) == NULL) {
			sprintf(str, "Failed to open file:\n%s", filename);
			MMessageDialog("Error", str, " Ok ", NULL);
			return NULL;
		}
		*ro = True;
	}
	else {
		*ro = False;
	}
	if ((buff = malloc((int)sb.st_size+1)) == NULL) {
		MMessageDialog("ERROR", "Not Enough Memory,\nSorry", " Ok ", NULL);
	}
	else {
		nread = fread(buff, 1, (int)sb.st_size, fp);
		buff[nread] = '\0';
	}
	fclose(fp);
	return buff;
}


/*
 * This callback handles cursor position change showing
 */
void CursorPosCB(MOBJECT p, EDIT_CURS *pc, void *ad)
{
	FILE_DATA       *pfd;
	MOBJECT         shell;
	char            buff[64];

	shell = MObjectShell(p);
	pfd = (FILE_DATA *)MObjectGetUserData(shell);
	if (pfd == NULL)
		return;
	sprintf(buff, "%4d", pc->pos_x + 1);
	MObjectSetText(pfd->curs_x_label, buff);
	sprintf(buff, "%4d", pc->pos_y + 1);
	MObjectSetText(pfd->curs_y_label, buff);
}

void AddUndoData(FILE_DATA *pfd,
	char *oldtext, int start, int oldlen,
	char *newtext, int newlen)
{
	UNDO_DATA       *pud, *tmp;

	if (pfd->curr_undo || pfd->first_undo) {
/*
 * Cut any Undo-ed data (it cannot be Redo-ed)
 */
		if (pfd->curr_undo) {
			pud = pfd->curr_undo->next;
			pfd->curr_undo->next = NULL;
		}
		else {
			pud = pfd->first_undo;
			pfd->first_undo = NULL;
		}
		while (pud) {
			tmp = pud;
			pud = pud->next;
			FreeUndo(tmp);
			pfd->undo_level--;
		}
	}

	if (pfd->undo_level == UNDO_DEPTH) {
/*
 * Cut the oldest undo data when maximum depth is reached
 */
		tmp = pfd->first_undo;
		pfd->first_undo = pfd->first_undo->next;
		if (pfd->first_undo)
			pfd->first_undo->prev = NULL;
		FreeUndo(tmp);
		pfd->undo_level--;
	}

	pud = (UNDO_DATA *)calloc(1, sizeof(UNDO_DATA));
	if (pud == NULL) {
		if (oldtext)
			free(oldtext);
		if (newtext)
			free(newtext);
		return;
	}

	pud->start = start;
	pud->oldlen = oldlen;
	pud->newlen = newlen;
	pud->oldtext = oldtext;
	pud->newtext = newtext;

	if (pfd->curr_undo)
		pfd->curr_undo->next = pud;
	pud->prev = pfd->curr_undo;
	pfd->curr_undo = pud;
	if (pfd->first_undo == NULL)
		pfd->first_undo = pud;

	pfd->undo_level++;
}

/*
 * This callback handles the 'modified' status and queues undo items
 */
void TextChangedCB(MOBJECT p, EDIT_CHANGE *ped, void *ad)
{
	FILE_DATA       *pfd;
	MOBJECT         shell;
	char            *oldtext = NULL;
	char            *newtext = NULL;

	shell = MObjectShell(p);
	pfd = MObjectGetUserData(shell);

	if (!pfd->modified) {
/*
 * Set file modified status to True
 */
		MObjectSetText(pfd->modified_label, "*");
		pfd->modified = True;
	}
	if (ped->len > 0 && (oldtext = malloc(ped->len+1)) == NULL) {
		return;
	}
	if (ped->change_len > 0 && (newtext = malloc( ped->change_len+1)) == NULL) {
		if (oldtext)
			free(oldtext);
		return;
	}
	if (ped->len > 0) {
		strncpy(oldtext, ped->current_text+ped->pos, ped->len);
		oldtext[ped->len] = '\0';
	}
	if (ped->change_len > 0) {
		strncpy(newtext, ped->change, ped->change_len);
		newtext[ped->change_len] = '\0';
	}
	AddUndoData(pfd, oldtext, ped->pos, ped->len, newtext, ped->change_len);
}

/*
 * This callback handles user's undo requests
 */
void UndoCB(MOBJECT p, void *od, void *ad)
{
	FILE_DATA       *pfd;
	UNDO_DATA       *pud;
	MOBJECT         shell;

	shell = MObjectShell(ad);
	pfd = MObjectGetUserData(shell);
	pud = pfd->curr_undo;
	if (pud == NULL) {
		MBeep();
		return;
	}
	MEditChangeText(pfd->edit,
		pud->start, pud->newlen,
		(pud->oldtext ? pud->oldtext : ""),
		pud->oldlen);
	pfd->curr_undo = pud->prev;
	if (!pfd->modified) {
/*
 * Set file modified status to True
 */
		MObjectSetText(pfd->modified_label, "*");
		pfd->modified = True;
	}
}

/*
 * This callback handles user's redo requests
 */
void RedoCB(MOBJECT p, void *od, void *ad)
{
	FILE_DATA       *pfd;
	UNDO_DATA       *pud;
	MOBJECT         shell;

	shell = MObjectShell(ad);
	pfd = MObjectGetUserData(shell);
	pud = (pfd->curr_undo ? pfd->curr_undo->next : pfd->first_undo);
	if (pud == NULL) {
		MBeep();
		return;
	}
	MEditChangeText(pfd->edit,
		pud->start, pud->oldlen,
		(pud->newtext ? pud->newtext : ""),
		pud->newlen);
	pfd->curr_undo = pud;
	if (!pfd->modified) {
/*
 * Set file modified status to True
 */
		MObjectSetText(pfd->modified_label, "*");
		pfd->modified = True;
	}
}

/*
 * This callback handles user's save request
 */
void SaveCB(MOBJECT p, void *od, void *ad)
{
	MOBJECT         shell = (MOBJECT)ad;
	FILE_DATA       *pfd = (FILE_DATA *)MObjectGetUserData(shell);
	FILE            *fp;
	char	str[256];
	char	*buff;
	int		len;

	if (pfd->pathname[0] == '\0') {
		if (pfd->modified) {
			if (!MFileSelection("Save File As ...", EXT,
			     pfd->filename, pfd->pathname, True))
				return;
			strcat(pfd->pathname, pfd->filename);
			MObjectSetText(pfd->fname_label, pfd->pathname);
		}
		else
			MMessageDialog("Warning", "No file open !", " Ok ", NULL);
		return;
	}
	if (pfd->read_only) {
		sprintf(str, "File: %s\nis read only!", pfd->pathname);
		MMessageDialog("Warning", str, " Ok ", NULL);
		return;
	}
	if (!pfd->modified) {
		sprintf(str, "File:\n%s\nhas not been modified.\nSave anyway ?", pfd->pathname);
		if (MMessageDialog("Warning", str, " Yes ", " Abort", NULL) != 0)
			return;
	}
	if ((fp = fopen(pfd->pathname, "w")) == NULL) {
		sprintf(str, "Cannot open file:\n%s\nfor writing!", pfd->pathname);
		MMessageDialog("Warning", str, " Ok ", NULL);
		return;
	}
	buff = MObjectGetText(pfd->edit, NULL);
	if (buff) {
		len = strlen(buff);
		if (fwrite(buff, 1, len, fp) != len)
			MMessageDialog("Error", "Write failed !!!", "Ok", NULL);
		free(buff);
	}
	fclose(fp);
	pfd->modified = False;
	MObjectSetText(pfd->modified_label, " ");
/*      FreeUndoList(pfd);
*/
}

/*
 * This callback handles user's save-as request
 */
void SaveAsCB(MOBJECT p, void *od, void *ad)
{
	char            pname[MAXPATHLEN];
	char            fname[MAXFNAMELEN];
	MOBJECT         shell = (MOBJECT)ad;
	FILE_DATA       *pfd = (FILE_DATA *)MObjectGetUserData(shell);
	FILE            *fp;
	char	str[256];
	char	*buff;
	int	len;

	strcpy(fname, pfd->filename);
	if (!MFileSelection("Save File As ...", EXT, fname, pname, True))
		return;
	strcat(pname, fname);
	if ((fp = fopen(pname, "w")) == NULL) {
		sprintf(str, "Cannot open file:\n%s\nfor writing!", pname);
		MMessageDialog("Warning", str, " Ok ", NULL);
		return;
	}
	buff = MObjectGetText(pfd->edit, NULL);
	if (buff) {
		len = strlen(buff);
		if (fwrite(buff, 1, len, fp) != len)
			MMessageDialog("Error", "Write failed !!!", "Ok", NULL);
		free(buff);
	}
	fclose(fp);
	pfd->modified = False;
	MObjectSetText(pfd->modified_label, " ");
	if (pfd->read_only) {
		pfd->read_only = False;
		MObjectSetSensitive(pfd->edit);
	}
	strcpy(pfd->pathname, pname);
	strcpy(pfd->filename, fname);
	MObjectSetText(pfd->fname_label, pfd->pathname);
	MObjectSetText(shell, pfd->filename);
}

/*
 * This callback handles user's request to reload the file from disk
 */
void RevertCB(MOBJECT p, void *od, void *ad)
{
	MOBJECT         shell = (MOBJECT )ad;
	FILE_DATA       *pfd = (FILE_DATA *)MObjectGetUserData(shell);
	char            str[256];
	char            *buff;

	if (pfd->pathname[0] == '\0') {
		MMessageDialog("Warning", "No file open !", " Ok ", NULL);
		return;
	}
	sprintf(str, "Are you sure you want to reload:\n\n%s ?\n", pfd->pathname);
	if (MMessageDialog("", str, " Yes ", " Abort ", NULL) != 0)
		return;
	if ((buff = LoadFile(pfd->pathname, &(pfd->read_only))) == NULL)
		return;
	pfd->modified = False;
	MObjectSetText(pfd->modified_label, pfd->read_only ? "R" : " ");
	MObjectSetText(pfd->edit, buff);
	free(buff);
	FreeUndoList(pfd);
}

/*
 * This callback handles user's close request
 */
void CloseCB(MOBJECT p, void *od, void *ud)
{
	MOBJECT         shell = (MOBJECT )ud;
	FILE_DATA       *pfd = (FILE_DATA *)MObjectGetUserData(shell);
	char            str[256];
	int             ret, ii, kk, is_last;

	if (pfd && pfd->modified) {
		if (p != NULL && pfd->pathname[0] == '\0') {
			if (MMessageDialog("Warning", "This window content\nwill be lost !",
			    " Save ", " Don't save ", NULL) == 0)
				SaveAsCB(p, od, ud);
		}
		else if (pfd->pathname[0]) {
			sprintf(str, "Save\n%s\nbefore exiting ?", pfd->pathname);
			ret = MMessageDialog("Warning",
				str, " Yes ", " No ", " Cancel ", NULL);
			if (ret == 0)
				SaveCB(p, od, ud);
			else if (ret == 2)
				return;
		}
	}
	pfd->filename[0] = '\0';
	pfd->pathname[0] = '\0';
	MObjectSetText(pfd->edit, "");
	MObjectSetText(pfd->fname_label, "");
	is_last = True;
	for (ii=kk=0; ii < MAX_N_WINDOW; ii++)
		if (windows[ii] == shell) {
			kk = ii;
			windows[ii] = NULL;
		}
		else if (windows[ii] != NULL)
			is_last = False;
	if (is_last && p != NULL) {
		if (MMessageDialog("Warning",
		    "This is last window!\nDo you want to quit ?",
		    " Yes ", " No ", NULL)) {
			windows[kk] = shell;
			MObjectSetText(shell, MEDIT_TITLE);
			pfd->modified = False;
			MObjectSetText(pfd->modified_label, " ");
			return;
		}
		MGUITerm();
		exit(0);
	}
	if (pfd->search_text)
		free(pfd->search_text);
	if (pfd->replace_text)
		free(pfd->replace_text);
	free(pfd);
	MShellDestroy(shell);
}

/*
 * This function creates an empty new window
 */
static int NewWindow(void)
{
	MOBJECT shell;
	int     ii;

	for (ii=0; ii < MAX_N_WINDOW; ii++)
		if (windows[ii] == NULL)
			break;
	if (ii == MAX_N_WINDOW)
		return -1;
	shell = MDCreatemain_shell();
	MObjectSetText(shell, MEDIT_TITLE);
	MShellSetWMCloseCallback(shell, CloseCB, shell);
	windows[ii] = shell;
	SetWindowOptions(shell);
	return ii;
}

/*
 * This callback handles user's open new file request
 */
void OpenNewCB(MOBJECT p, void *od, void *ad)
{
	MOBJECT         shell;
	FILE_DATA       *pfd;
	char            fname[MAXFNAMELEN];
	char            pname[MAXPATHLEN];
	char            *buff;
	int		ii;

	fname[0] = '\0';
	pname[0] = '\0';
	if (!MFileSelection("Open New File", EXT, fname, pname, True))
		return;
	ii = NewWindow();
	if (ii == -1) {
		char str[64];

		sprintf(str, "You cannot open\nmore than %d windows", MAX_N_WINDOW);
		MMessageDialog("Warning", str, " Ok ", NULL);
		return;
	}
	shell = windows[ii];
	MShellRealizeXY(shell, ii*30, ii*30);
	pfd = (FILE_DATA *)MObjectGetUserData(shell);
	strcpy(pfd->filename, fname);
	strcpy(pfd->pathname, pname);
	strcat(pfd->pathname, pfd->filename);
	if ((buff = LoadFile(pfd->pathname, &(pfd->read_only))) == NULL)
		return;
	MObjectSetSensitivity(pfd->edit, !pfd->read_only);
	pfd->modified = False;
	MObjectSetText(pfd->modified_label, pfd->read_only ? "R" : " ");
	MObjectSetText(pfd->fname_label, pfd->pathname);
	MObjectSetText(shell, pfd->filename);
	MObjectSetText(pfd->edit, buff);
	free(buff);
	FreeUndoList(pfd);
}

/*
 * This callback handles user's load file request
 */
void LoadFileCB(MOBJECT p, void *od, void *ad)
{
	MOBJECT         shell = (MOBJECT)ad;
	FILE_DATA       *pfd = (FILE_DATA *)MObjectGetUserData(shell);
	char            str[256];
	char            fname[MAXFNAMELEN];
	char            pname[MAXPATHLEN];
	char            *buff;
	int             ret;

	if (pfd && pfd->modified) {
		if (p != NULL && pfd->pathname[0] == '\0') {
			if (MMessageDialog("Warning", "This window content\nwill be lost !",
			    " Save ", " Don't save ", NULL) == 0)
				SaveAsCB(p, od, ad);
		}
		else if (pfd->pathname[0]) {
			sprintf(str, "Save current file:\n%s ?", pfd->pathname);
			ret = MMessageDialog("Warning",
				str, " Yes ", " No ", " Cancel ", NULL);
			if (ret == 0)
				SaveCB(p, od, ad);
			else if (ret == 2)
				return;
		}
	}
	fname[0] = '\0';
	pname[0] = '\0';
	if (!MFileSelection("Load File", EXT, fname, pname, True))
		return;
	strcpy(pfd->filename, fname);
	strcpy(pfd->pathname, pname);
	strcat(pfd->pathname, pfd->filename);
	if ((buff = LoadFile(pfd->pathname, &(pfd->read_only))) == NULL)
		return;
	MObjectSetSensitivity(pfd->edit, !pfd->read_only);
	pfd->modified = False;
	MObjectSetText(pfd->modified_label, pfd->read_only ? "R" : " ");
	MObjectSetText(pfd->fname_label, pfd->pathname);
	MObjectSetText(shell, pfd->filename);
	MObjectSetText(pfd->edit, buff);
	free(buff);
	FreeUndoList(pfd);
}

/*
 * This callback handles user's request to insert a file at
 * the current cursor position
 */
void InsertFileCB(MOBJECT p, void *od, void *ad)
{
	MOBJECT         shell = (MOBJECT)ad;
	FILE_DATA       *pfd = (FILE_DATA *)MObjectGetUserData(shell);
	char            fname[MAXFNAMELEN];
	char            pname[MAXPATHLEN];
	char            *buff;
	int             len, dummy;
	int             curs_pos;

	fname[0] = '\0';
	pname[0] = '\0';
	if (!MFileSelection("Insert File", EXT, fname, pname, True))
		return;
	strcat(pname, fname);
	if ((buff = LoadFile(pname, &dummy)) == NULL)
		return;
	curs_pos = MEditGetCursorPos(pfd->edit);
	len = strlen(buff);
	MEditChangeText(pfd->edit, curs_pos, 0, buff, len);
	AddUndoData(pfd, NULL, curs_pos, 0, buff, len);
}

/*
 * This callback handles user's request to save
 * the selected text in to a file
 */
void WriteSelCB(MOBJECT p, void *od, void *ud)
{
	MOBJECT         shell = (MOBJECT )ud;
	FILE_DATA       *pfd = (FILE_DATA *)MObjectGetUserData(shell);
	FILE		*fp;
	int		start, end;
	char		*buff;
	char		str[256];
	char            fname[MAXFNAMELEN];
	char            pname[MAXPATHLEN];

	MEditGetSelection(pfd->edit, &start, &end);
	if (start >= end) {
		MMessageDialog("Warning", "No text selected!", "Ok", NULL);
		return;
	}
	if ((buff = malloc(end-start+1)) == NULL) {
		MBeep();
		return;
	}
	MEditGetSubString(pfd->edit, start, end, buff);
	fname[0] = '\0';
	if (MFileSelection("Write Selection", EXT, fname, pname, True)) {
		strcat(pname, fname);
		if (access(pname, R_OK) == 0 &&
		    MMessageDialog("Warning", "File exists!\nOverwrite ?",
				   " Yes ", " No ", NULL) != 0) {
			free(buff);
			return;
		}
		if ((fp = fopen(pname, "w")) != NULL) {
			if (fwrite(buff, 1, end-start, fp) != end-start)
				MMessageDialog("Error", "Writing file", "Ok", NULL);
			fclose(fp);
		}
		else {
			sprintf(str, "Cannot open file:\n%s\nfor writing!", pname);
			MMessageDialog("Warning", str, " Ok ", NULL);
		}
	}
	free(buff);
}

/*
 * This callback handles user's request to print
 * the selected text or the entire text stream
 */
void PrintCB(MOBJECT p, void *od, void *ud)
{
	MOBJECT         shell = (MOBJECT )ud;
	FILE_DATA       *pfd = (FILE_DATA *)MObjectGetUserData(shell);
	FILE		*fp;
	int		start, end, ret;
	char		*buff;
	char		str[256];
	char            fname[MAXFNAMELEN];

	switch(MMessageDialog("", "Print...", "File", "Selection", "Cancel", NULL)) {
		case 2:
			return;
		case 1:
			MEditGetSelection(pfd->edit, &start, &end);
			if (start >= end) {
				MMessageDialog("Warning", "No text selected!", "Ok", NULL);
				return;
			}
			if ((buff = malloc(end-start+1)) == NULL) {
				MBeep();
				return;
			}
			MEditGetSubString(pfd->edit, start, end, buff);
			break;
		default:
			buff = MObjectGetText(pfd->edit, NULL);
			if (buff == NULL) {
				MBeep();
				return;
			}
			start = 0;
			end = strlen(buff);
	}
	strcpy(fname, "meXXXXXX");
	mktemp(fname);
	if ((fp = fopen(fname, "w")) != NULL) {
		fwrite(buff, 1, end-start, fp);
		fclose(fp);
		free(buff);
	}
	else {
		sprintf(str, "Cannot open file:\n%s\nfor writing!", fname);
		MMessageDialog("Warning", str, " Ok ", NULL);
		free(buff);
		return;
	}
	for (;;) {
	    switch(MSpoolTempFile(fname)) {
		case MSPOOL_NOT_READY:
		    ret = MMessageDialog("Error", "Printer NOT READY", "Retry", "Cancel", NULL);
		    if (ret == 0)
			continue;
		    break;
		default:
		    MMessageDialog("Error", "Print failed!", "Ok", NULL);
		    break;
		case MSPOOL_OK:
		    return;
	    }
	    unlink(fname);
	    return;
	}
}

/*
 * This callback handles user's request to open an empty new window
 */
void NewCB(MOBJECT p, void *od, void *ad)
{
	int     ii;

	ii = NewWindow();
	if (ii == -1) {
		char str[64];

		sprintf(str, "You cannot open\nmore than %d windows", MAX_N_WINDOW);
		MMessageDialog("Warning", str, " Ok ", NULL);
		return;
	}
	MShellRealizeXY(windows[ii], ii*30, ii*30);
}

/*
 * This callback handles user's quit request
 */
void QuitCB(MOBJECT p, void *od, void *ud)
{
	int     ii;

	for (ii=0; ii < MAX_N_WINDOW; ii++)
		if (windows[ii] != NULL)
			CloseCB(NULL, od, windows[ii]);
	for (ii=0; ii < MAX_N_WINDOW; ii++)
		if (windows[ii] != NULL)
			return;
	MGUITerm();
	exit(0);
}

/*
 * Convert the name supplied by the user in the command line
 * in the complete pathname and the filename
 */
void FilePathName(char *name, char *fname, char *pname)
{
#ifdef UNIX
	if (*name == DIR_SEP)
#else
	if (*name == DIR_SEP || *name == '.' || name[1] == ':')
#endif
		strcpy(pname, name);
	else
		sprintf(pname, "%s%s", MGetCurrentDirectory(), name);
	strcpy(fname, strrchr(pname, DIR_SEP) + 1);
}

/*
 * Access point to M-Edit program
 */
void MGUIMain(int argc, char **argv)
{
	char            *buff;
	FILE_DATA       *pfd;

#ifdef UNIX
	buff = getenv("HOME");
	sprintf(pref_fname, "%s/.medit", (buff ? buff : "."));
#else
	strcpy(pref_fname, argv[0]);
	strcpy(pref_fname + strlen(pref_fname) - 3, "cfg");
#endif
	LoadPrefs();
	NewCB(NULL, NULL, NULL);
	pfd = MObjectGetUserData(windows[0]);
	if (argc > 1) {
		FilePathName(argv[1], pfd->filename, pfd->pathname);
		if (access(pfd->pathname, R_OK) == 0 &&
		    (buff = LoadFile(pfd->pathname, &(pfd->read_only))) != NULL) {
			MObjectSetSensitivity(pfd->edit, !pfd->read_only);
			MObjectSetText(pfd->modified_label,
				       pfd->read_only ? "R" : " ");
			MObjectSetText(pfd->edit, buff);
			free(buff);
		}
		pfd->modified = False;
		MObjectSetText(pfd->fname_label, pfd->pathname);
		MObjectSetText(windows[0], pfd->filename);
	}
	else
		MObjectSetText(pfd->fname_label, MEDIT_COPY);
	MMainLoop();
}

