/*
 Program WinCaml: Graphical User Interface
 for interactive use of Caml-Light and Ocaml.
 Copyright (C) 2005-2017 Jean Mouric 35700 Rennes France
 email: jean.mouric@orange.fr
 
 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 3 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, see <http://www.gnu.org/licenses/>.
 */

// File CChildFrame.cpp

#include "CChildFrame.h"
#include "CFrame.h"
#include "CHighlighter.h"
#include "CInput.h"
#include "COutput.h"
#include "CSplitter.h"
#include "CUndoManager.h"
#include <sstream>
#include <locale>

CProcess* startCaml(bool ocaml);
wstring extension(const wstring& fileName);
wstring fromLatin1(const string& str);

CChildFrame::CChildFrame(CFrame* mdiFrame, bool maximized) : CMDIChildFrame(mdiFrame, maximized)
{
    cFrame = mdiFrame;
    process = NULL;
    splitter = NULL;
    setConfig();
    textEdit = cInput = new CInput(this);
    cOutput = new COutput(this);
    setSearchEdit(textEdit);
    
    splitter = new CSplitter(this, cInput, cOutput, SplitterViewMode, xSplit, xDim, ySplit, yDim, VerticalBar);
    
    cInput->setWrapping(WrapInput);
    cOutput->setWrapping(WrapOutput);
    
    currentCommand = 0;
    commandArray = new deque<wstring>();
    commandInfoArray = new deque<CommandInfo>();
    
    this->startTimer();
    
    if (maximized)
		showMaximized();
    else
		showNormal();
}
CChildFrame::~CChildFrame()
{
	delete splitter;
	splitter = NULL;
	textEdit = NULL;
	delete cInput;
	cInput = NULL;
	delete cOutput;
	cOutput = NULL;
	if (process)
	{
		process->stop();
		delete process;
		process = NULL;
	}
	delete commandArray;
	delete commandInfoArray;
}
void CChildFrame::setConfig()
{
	IndentWithTabs = cFrame->IndentWithTabs;
	IndentAfterIn = cFrame->IndentAfterIn;
	IndentFilters = cFrame->IndentFilters;
	UseOCamlIndenter = cFrame->UseOCamlIndenter;
	SpaceCountPerTab = cFrame->SpaceCountPerTab;
    
	VerticalBar = cFrame->VerticalBar;
	xSplit = cFrame->xSplit;
	xDim = cFrame->xDim;
	ySplit = cFrame->ySplit;
	yDim = cFrame->yDim;
    
	InputFontSize = cFrame->InputFontSize;
	OutputFontSize = cFrame->OutputFontSize;
	InputFontName = cFrame->InputFontName;
	OutputFontName = cFrame->OutputFontName;
    
	WrapInput = cFrame->WrapInput;
	WrapOutput = cFrame->WrapOutput;
    
	SplitterViewMode = cFrame->SplitterViewMode;
    
	SyntaxColoring = cFrame->SyntaxColoring;
    
	OutputMode = cFrame->OutputMode;
    
	CommentColor = cFrame->CommentColor;
	DelimiterColor = cFrame->DelimiterColor;
	KeywordColor = cFrame->KeywordColor;
	NumberColor = cFrame->NumberColor;
	OperatorColor = cFrame->OperatorColor;
	StringColor = cFrame->StringColor;
	InputCommandBackground = cFrame->InputCommandBackground;
	OutputCommandForeground = cFrame->OutputCommandForeground;
	InputBufferBackground = cFrame->InputBufferBackground;
	OtherColor = cFrame->OtherColor;
    
	PreferredEncoding = cFrame->PreferredEncoding;
	AutomaticEncoding = cFrame->AutomaticEncoding;
    
	CamlTop = cFrame->CamlTop;
	StartNow = cFrame->StartNow;
    
	font1 = cFrame->font1;
	font2 = cFrame->font2;
}
void CChildFrame::newFile()
{
	isNewFile = true;
	wstringstream ss;
	ss << L"Sans titre " << cFrame->newFileCount++;
	title = ss.str();
	setTitle(title);
	cInput->undoManager->start();
	if (StartNow)
		startProcess(cInput->getText());
	updateMenus(true);
}
bool CChildFrame::openFile(const wstring& fileName)
{
	if(cInput->loadFile(fileName, AutomaticEncoding, PreferredEncoding))
	{
		cInput->setSelection((size_t)-1, (size_t)-1);
		cFrame->PreferredEncoding = PreferredEncoding;
		isNewFile = false;
		title = fileName;
		setTitle(title.substr(title.find_last_of(L"\\") + 1));
        wstring ext = extension(fileName);
		if (StartNow && ext != L"MLI")
			startProcess(cInput->getText());
        cInput->textHasChanged();
		cInput->highlighter->colorize();
        cInput->undoManager->setSelection();
		cInput->undoManager->start();
		updateMenus(true);
		return true;
	}
	return false;
}
void CChildFrame::includeFile()
{
	wstring fName = L"";
	if (cFrame->openFileDialog(fName))
	{
		cInput->undoManager->setType(UR_INCLUDE);
		size_t l = cInput->getTextLength();
		cInput->appendFile(fName, PreferredEncoding);
		cInput->textHasChanged();
		cInput->undoManager->setType(UR_TYPING);
		if (process && process->isRunning())
		{
			cInput->addCommands((cInput->getText()).substr(l));
		}
		l = cInput->getTextLength();
		cInput->setSelection(l,l);
	}
}
void CChildFrame::startProcess(const wstring& s)
{
	cOutput->reset();
	wstring ext = extension(title);
	if (ext == L"OML")
	{
		CamlTop = OCAML;
	}
    else
    {
        CamlTop = cFrame->CamlTop;
    }
    process = startCaml(CamlTop == OCAML);
	if (process)
	{
		updateCamlMenu(true);
		if (s.length() != 0)
		{
			cInput->addCommands(s);
		}
	}
	else
	{
		errorMessage(L"Impossible de lancer caml!");
	}
}
void CChildFrame::reset(int p)
{
	currentCommand = p;
	int q = p;
	int n = (int)commandArray->size();
	for (q = p; q < n; q++)
	{
		commandArray->pop_back();
	}
	n = (int)commandInfoArray->size();
	for (q = p; q < n; q++)
	{
		commandInfoArray->pop_back();
	}
}
void CChildFrame::onTimer()
{
	if (!cFrame->mdiChildren.empty() && cFrame->mdiChildren.at(0) != this) return;
    if (cInput)
    {
        cInput->textHasChanged();
        cInput->highlighter->colorize();
/*
        if (cInput->selectionChanged && process && process->isRunning())
        {
            size_t selStart, selEnd;
            cInput->getSelection(selStart, selEnd);
            cFrame->enableMenuItem(CAML_SEND_SEL, cInput->inBuffer && selStart != selEnd);
        }
*/
    }
	if (textEdit && textEdit->selectionChanged)
	{
		textEdit->selectionChanged = false;
		updateCopyAndCutMenus();
		cFrame->setStatus(0, textEdit->status());
	}
	if (process && process->isRunning())
	{
		cOutput->handleCommand(process);
		cOutput->listen(process);
	}
	else if (process)
	{
        process->stop();
		delete process;
		process = NULL;
		updateCamlMenu(true);
        
#ifdef _MSVC98_
		cOutput->setText(cOutput->getTextLength(), 0, L"Caml a quitt\xE9!\n", rgb(255, 0, 0));
#else
		cOutput->setText(cOutput->getTextLength(), 0, L"Caml a quitt\u00E9!\n", rgb(255, 0, 0));
#endif
        
	}
}
void CChildFrame::onFileSave()
{
	if (isNewFile)
	{
		onFileSaveAs();
	}
    else if (cInput->saveFile(title, PreferredEncoding))
	{
		cFrame->setStatus(1, title);
		setTitle(title.substr(title.find_last_of(L"\\") + 1));
		cInput->undoManager->stop();
		cInput->undoManager->start();
		updateUndoMenuTitle();
		updateRedoMenuTitle();
	}
}
void CChildFrame::onFileSaveAsFormatted()
{
	wstring fName = title.substr(title.find_last_of(L"\\") + 1);
	fName = fName.substr(0, fName.find_last_of(L"."));
	if (cFrame->saveFormattedDocumentDialog(fName))
	{
		size_t selStart, selEnd;
		cInput->getSelection(selStart, selEnd);
		cInput->highlighter->colorizeAll();
		cInput->setTextDefaultBackground(cInput->commandStart, cInput->commandEnd - cInput->commandStart);
		cInput->saveFormattedDocument(fName);
		cInput->setTextBackground(cInput->commandStart, cInput->commandEnd - cInput->commandStart, this->InputCommandBackground);
		cInput->setSelection(selStart, selEnd);
		cInput->updateView();
	}
}
void CChildFrame::onFileSaveAs()
{
save:	wstring fName = title.substr(title.find_last_of(L"\\") + 1);
	if (cFrame->saveFileDialog(fName))
	{
        if (extension(title) != L"OML" && extension(fName) == L"OML" && !(process && process->isRunning() && CamlTop == OCAML))
        {
#ifdef _MSVC98_
                errorMessage(L"L'extension oml ne peut \xEAtre choisie en l'absence de processus ocaml actif!");
#else
                errorMessage(L"L'extension oml ne peut \u00EAtre choisie en l'absence de processus ocaml actif!");
#endif
                goto save;
        }
        if(cInput->saveFile(fName, PreferredEncoding))
		{
			isNewFile = false;
			title = fName;
			cFrame->setStatus(1, title);
			setTitle(title.substr(title.find_last_of(L"\\") + 1));
			cInput->undoManager->stop();
			cInput->undoManager->start();
			updateUndoMenuTitle();
			updateRedoMenuTitle();
			cFrame->updateRecentFiles(title,false);
			cFrame->updateRecentFilesMenus();
		}
	}
}
bool CChildFrame::reviewChange()
{
	if (cInput->undoManager->getUndoType() != UR_NONE)
	{
		cFrame->setActiveChild(this);
#ifdef _MSVC98_
		wstring message = L"Le fichier " + title.substr(title.find_last_of(L"\\") + 1) + L" a chang\xE9\n";
#else
		wstring message = L"Le fichier " + title.substr(title.find_last_of(L"\\") + 1) + L" a chang\u00E9\n";
#endif
		message += L"Enregistrer les changements ?";
		int res = yesnocancelMessage(message);
		switch(res)
		{
            case idCancel:
                return true;
            case idYes:
                onFileSave();
                break;
            case idNo:
                cInput->undoManager->stop();
                hide();
                break;
            default:
                break;
		}
	}
	return false;
}
void CChildFrame::onClose()
{
	cInput->undoManager->stop();
	if (cFrame->mdiChildren.size() == 1)
		closeFindDialog();
	CMDIChildFrame::onClose();
}
void CChildFrame::onDestroy()
{
	if (cFrame->mdiChildren.size() == 1 && !cFrame->closing)
	{
		cFrame->setConfig(this);
		updateMenus(false);
	}
	for (size_t i = 0; i < cFrame->mdiChildren.size(); i++)
	{
		if (cFrame->mdiChildren.at(i) == this)
		{
			cFrame->mdiChildren.erase(cFrame->mdiChildren.begin() + i);
			break;
		}
	}
	if (cFrame->mdiChildren.size() != 0)
	{
		cFrame->clearFont(font1);
		cFrame->clearFont(font2);
	}
	CMDIChildFrame::onDestroy();
	delete this;
}
void CChildFrame::onActivate()
{
	if (!cFrame->closing)
	{
		for (size_t i = 0; i < cFrame->mdiChildren.size(); i++)
		{
			if (cFrame->mdiChildren.at(i) == this)
			{
				cFrame->mdiChildren.erase(cFrame->mdiChildren.begin() + i);
				cFrame->mdiChildren.push_front(this);
				break;
			}
		}
		updateMenus(true);
		textEdit->focus();
		setSearchEdit(textEdit);
		cFrame->setConfig(this);
	}
}
void CChildFrame::onSize()
{
    if (!splitter) return;
    splitter->zoom();
    cFrame->xSplit = xSplit = splitter->xSplit;
    cFrame->xDim = xDim = splitter->xDim;
    cFrame->ySplit = ySplit = splitter->ySplit;
    cFrame->yDim = yDim = splitter->yDim;
}
void CChildFrame::onLeftButtonDown(int x, int y)
{
	if (!splitter) return;
	splitter->onLeftButtonDown(x, y);
}
void CChildFrame::onLeftButtonUp()
{
	if (!splitter) return;
	splitter->onLeftButtonUp();
}
void CChildFrame::onMouseMove(int x, int y, bool leftButtonDown)
{
	if (!splitter) return;
	splitter->onMouseMove(x, y, leftButtonDown);
	cFrame->xSplit = xSplit = splitter->xSplit;
	cFrame->ySplit = ySplit = splitter->ySplit;
	cFrame->xDim = xDim = splitter->xDim;
	cFrame->yDim = yDim = splitter->yDim;
}
void CChildFrame::onEditCut()
{
	cInput->doCut();
}
void CChildFrame::onEditCopy()
{
	textEdit == cInput ? cInput->doCopy() : cOutput->copy();
}
void CChildFrame::onEditPaste()
{
	cInput->doPaste();
}
void CChildFrame::onEditSelectAll()
{
	textEdit->selectAll();
	updateMenus(true);
}
void CChildFrame::onCommand(int cmd)
{
	switch(cmd)
	{
        case FILE_INCLUDE:
            includeFile();
            break;
        case FILE_SAVE:
            onFileSave();
            break;
        case FILE_SAVEAS:
            onFileSaveAs();
            break;
        case FILE_SAVEASFORMATTED:
            onFileSaveAsFormatted();
            break;
        case FILE_PRINT:
            cInput->printFormattedDialog();
            break;
        case EDIT_UNDO:
            cInput->undo();
            setStatus();
            break;
        case EDIT_REDO:
            cInput->redo();
            setStatus();
            break;
        case EDIT_CUT:
            onEditCut();
            break;
        case EDIT_COPY:
            onEditCopy();
            break;
        case EDIT_PASTE:
            onEditPaste();
            break;
        case EDIT_SELECTALL:
            onEditSelectAll();
            break;
        case EDIT_FIND:
            findDialog();
            break;
        case EDIT_REPLACE:
            findReplaceDialog();
            break;
        case EDIT_INDENTMODE:
            IndentWithTabs = !IndentWithTabs;
            cInput->setUseTabs(IndentWithTabs);
            cInput->setTabs(InputFontSize, SpaceCountPerTab);
            cOutput->setTabs(OutputFontSize, SpaceCountPerTab);
            break;
        case EDIT_TABWIDTH:
            SpaceCountPerTab = cFrame->SpaceCountPerTab;
            cInput->setTabs(InputFontSize, SpaceCountPerTab);
            cOutput->setTabs(OutputFontSize, SpaceCountPerTab);
            break;
        case EDIT_INDENTAFTERIN:
            IndentAfterIn = !IndentAfterIn;
            break;
        case EDIT_INDENTFILTER:
            IndentFilters = !IndentFilters;
            break;
        case EDIT_INDENTOCAML:
            UseOCamlIndenter = !UseOCamlIndenter;
            break;
        case EDIT_INDENT:
            cInput->indent();
            break;
        case VIEW_SPLIT:
            VerticalBar = !VerticalBar;
            splitter->setVertical(VerticalBar);
            break;
        case VIEW_INPUTONLY: case VIEW_OUTPUTONLY:case VIEW_BOTH:
            splitter->setViewMode(cmd);
            SplitterViewMode = cmd;
            break;
        case VIEW_INPUTFONT:
            InputFontName = cFrame->InputFontName;
            InputFontSize = cFrame->InputFontSize;
            font1 = cFrame->font1;
            cInput->setFont(font1);
            cInput->highlighter->textChanged = true;
            cInput->highlighter->invalidate();
            cInput->setTabs(InputFontSize, SpaceCountPerTab);
            cOutput->setTabs(OutputFontSize, SpaceCountPerTab);
            cInput->updateView();
            cOutput->updateView();
            break;
        case VIEW_OUTPUTFONT:
            OutputFontName = cFrame->OutputFontName;
            OutputFontSize = cFrame->OutputFontSize;
            font2 = cFrame->font2;
            cOutput->setFont(font2);
            cOutput->colorize();
            cInput->setTabs(InputFontSize, SpaceCountPerTab);
            cOutput->setTabs(OutputFontSize, SpaceCountPerTab);
            cInput->updateView();
            cOutput->updateView();
            break;
        case VIEW_WRAPINPUT:
            WrapInput = !WrapInput;
            cInput->setWrapping(WrapInput);
            break;
        case VIEW_WRAPOUTPUT:
            WrapOutput = !WrapOutput;
            cOutput->setWrapping(WrapOutput);
            break;
        case VIEW_SYNTAXCOLOR:
            SyntaxColoring = !SyntaxColoring;
            SyntaxColoring ? cInput->setColors() : cInput->removeColors();
            cInput->highlighter->textChanged = true;
            cInput->highlighter->invalidate();
            break;
        case COLOR_BUFFERBACKGROUND:
            InputBufferBackground = cFrame->InputBufferBackground;
            cInput->setColor(bufferBackground);
            cInput->highlighter->textChanged = true;
            break;
        case COLOR_COMMANDBACKGROUND:
            InputCommandBackground = cFrame->InputCommandBackground;
            cInput->setColor(inputBackground);
            cInput->highlighter->textChanged = true;
            break;
        case COLOR_OUTPUT:
            OutputCommandForeground = cFrame->OutputCommandForeground;
            cOutput->colorize();
            break;
        case COLOR_NUMBER:
            NumberColor = cFrame->NumberColor;
            cInput->setColor(numberColor);
            cInput->highlighter->textChanged = true;
            cInput->highlighter->updateColor(numberToken);
            break;
        case COLOR_KEYWORD:
            KeywordColor = cFrame->KeywordColor;
            cInput->setColor(keywordColor);
            cInput->highlighter->textChanged = true;
            cInput->highlighter->updateColor(keywordToken);
            break;
        case COLOR_DELIMITER:
            DelimiterColor = cFrame->DelimiterColor;
            cInput->setColor(delimiterColor);
            cInput->highlighter->textChanged = true;
            cInput->highlighter->updateColor(delimiterToken);
            break;
        case COLOR_OPERATOR:
            OperatorColor = cFrame->OperatorColor;
            cInput->setColor(operatorColor);
            cInput->highlighter->textChanged = true;
            cInput->highlighter->updateColor(operatorToken);
            break;
        case COLOR_STRING:
            StringColor = cFrame->StringColor;
            cInput->setColor(stringColor);
            cInput->highlighter->textChanged = true;
            cInput->highlighter->updateColor(stringToken);
            break;
        case COLOR_COMMENT:
            CommentColor = cFrame->CommentColor;
            cInput->setColor(commentColor);
            cInput->highlighter->textChanged = true;
            cInput->highlighter->updateColor(commentToken);
            break;
        case ENCODING_UNIX: case ENCODING_MAC: case ENCODING_WIN: case ENCODING_UTF8:
            PreferredEncoding = cFrame->PreferredEncoding;
            break;
        case ENCODING_AUTO:
            AutomaticEncoding = cFrame->AutomaticEncoding;
            break;
        case CAML_SEND:
            cInput->sendCommand();
            break;
/*
        case CAML_SEND_SEL:
            cOutput->getInputSelection();
            break;
*/
        case CAML_INTERRUPT:
            if (process)
            {
                if (process->interrupt())
				{
					reset(currentCommand);
				}
				else
				{
#ifdef _MSVC98_
                    errorMessage(L"L'envoi de Ctrl+Break a \xE9"L"chou\xE9!");
#else
                    errorMessage(L"L'envoi de Ctrl+Break a \u00E9chou\u00E9!");
#endif
				}
			}
            break;
        case CAML_STOP:
            if (process)
            {
                process->stop();
            }
            break;
        case CAML_CLEAROUTPUT:
            if (!(process && process->isRunning()))
            {
                cOutput->clear();
                cFrame->enableMenuItem(CAML_CLEAROUTPUT, false);
            }
            break;
        case CAMLTOP_START:
            StartNow = ! StartNow;
            break;
        case OUTPUT_SHORT: 	case OUTPUT_MEDIUM: case OUTPUT_LONG:
            cOutput->setMode(cmd);
            break;
        case HELP_DEFAULTCONFIG:
            if (cFrame->restoreDefaults)
            {
                restore();
            }
            break;
        default:
            break;
	}
}
void CChildFrame::restore()
{
	cFrame->clearFont(font1);
	cFrame->clearFont(font1);
	setConfig();
	updateMenus(true);
    showDefault();
	splitter->setViewMode(VIEW_BOTH);
	splitter->setVertical(VerticalBar);
    
	cInput->setWrapping(WrapInput);
	cInput->setFont(font1);
	cInput->setColors();
	cInput->highlighter->textChanged = true;
	cInput->highlighter->updateColors();
	cInput->setTabs(InputFontSize, SpaceCountPerTab);
	cInput->setColor(inputBackground);
	cInput->setColor(bufferBackground);
    
	cOutput->setWrapping(WrapOutput);
	cOutput->setFont(font2);
	cOutput->setTabs(OutputFontSize, SpaceCountPerTab);
	cOutput->setMode(OutputMode);
	cOutput->suspendLayout();
	cOutput->colorize();
	cOutput->resumeLayout();
	cOutput->updateView();
	cFrame->restoreDefaults = false;
}

#ifdef _MSVC98_
#define MODIFIED L" (non enregistr\xE9)"
#define UNMODIFIED L" (enregistr\xE9)"
#else
#define MODIFIED L" (non enregistr\u00E9)"
#define UNMODIFIED L" (enregistr\u00E9)"
#endif

void CChildFrame::updateUndoMenuTitle()
{
	int undoType = cInput->undoManager->getUndoType();
	setWindowModified(undoType != UR_NONE);
	switch (undoType)
	{
        case UR_TYPING:
            cFrame->setMenuItemText(EDIT_UNDO, L"Annuler la frappe\t" + undoShortCut(), true);
            cFrame->setStatus(1, title + (isNewFile ? L" (nouveau fichier)" : MODIFIED));
            break;
        case UR_CUT:
            cFrame->setMenuItemText(EDIT_UNDO, L"Annuler Couper\t" + undoShortCut(), true);
            cFrame->setStatus(1, title + (isNewFile ? L" (nouveau fichier)" : MODIFIED));
            break;
        case UR_PASTE:
            cFrame->setMenuItemText(EDIT_UNDO, L"Annuler Coller\t" + undoShortCut(), true);
            cFrame->setStatus(1, title + (isNewFile ? L" (nouveau fichier)" : MODIFIED));
            break;
        case UR_INDENT:
            cFrame->setMenuItemText(EDIT_UNDO, L"Annuler Indenter\t" + undoShortCut(), true);
            cFrame->setStatus(1, title + (isNewFile ? L" (nouveau fichier)" : MODIFIED));
            break;
        case UR_INCLUDE:
            cFrame->setMenuItemText(EDIT_UNDO, L"Annuler Inclure\t" + undoShortCut(), true);
            cFrame->setStatus(1, title + (isNewFile ? L" (nouveau fichier)" : MODIFIED));
            break;
        case UR_REPLACE:
            cFrame->setMenuItemText(EDIT_UNDO, L"Annuler Remplacer\t" + undoShortCut(), true);
            cFrame->setStatus(1, title + (isNewFile ? L" (nouveau fichier)" : MODIFIED));
            break;
        case UR_NONE:
            cFrame->setMenuItemText(EDIT_UNDO, L"Annuler\t" + undoShortCut(), false);
            cFrame->setStatus(1, title + (isNewFile ? L" (nouveau fichier)" : UNMODIFIED));
            break;
        default:
            break;
	}
}
#ifdef _MSVC98_
#define RETABLIR L"R\xE9tablir"
#else
#define RETABLIR L"R\u00E9tablir"
#endif
void CChildFrame::updateRedoMenuTitle()
{
	int redoType = cInput->undoManager->getRedoType();
	switch (redoType)
	{
        case UR_TYPING:
            cFrame->setMenuItemText(EDIT_REDO, (RETABLIR L" la frappe\t") + redoShortCut(), true);
            break;
        case UR_CUT:
            cFrame->setMenuItemText(EDIT_REDO, (RETABLIR L" Couper\t") + redoShortCut(), true);
            break;
        case UR_PASTE:
            cFrame->setMenuItemText(EDIT_REDO, (RETABLIR L" Coller\t") + redoShortCut(), true);
            break;
        case UR_INDENT:
            cFrame->setMenuItemText(EDIT_REDO, (RETABLIR L" Indenter\t") + redoShortCut(), true);
            break;
        case UR_INCLUDE:
            cFrame->setMenuItemText(EDIT_REDO, (RETABLIR L" Inclure\t") + redoShortCut(), true);
            break;
        case UR_REPLACE:
            cFrame->setMenuItemText(EDIT_REDO, (RETABLIR L" Remplacer\t") + redoShortCut(), true);
            break;
        case UR_NONE:
            cFrame->setMenuItemText(EDIT_REDO, (RETABLIR L"\t")  + redoShortCut(), false);
            break;
        default:
            break;
	}
}
void CChildFrame::updateCopyAndCutMenus()
{
	size_t selStart, selEnd;
	textEdit->getSelection(selStart, selEnd);
	if (selStart != selEnd)
	{
		cFrame->enableMenuItem(EDIT_COPY, true);
		if (textEdit == cInput)
		{
			cFrame->enableMenuItem(EDIT_CUT, true);
		}
		else
		{
			cFrame->enableMenuItem(EDIT_CUT, false);
		}
	}
	else
	{
		cFrame->enableMenuItem(EDIT_COPY, false);
		cFrame->enableMenuItem(EDIT_CUT, false);
	}
}
void CChildFrame::updateCamlMenu(bool enabled)
{
	if (enabled)
	{
		bool running = process && process->isRunning();
		bool clearOutput = !(running || cOutput->getTextLength() == 0);
		cFrame->enableMenuItem(CAML_SEND, true);
        size_t selStart, selEnd;
        cInput->getSelection(selStart, selEnd);
//        cFrame->enableMenuItem(CAML_SEND_SEL, cInput->inBuffer && selStart != selEnd);
		cFrame->enableMenuItem(CAML_INTERRUPT, running);
		cFrame->enableMenuItem(CAML_STOP, running);
		cFrame->enableMenuItem(CAML_CLEAROUTPUT, clearOutput);
	}
	else
	{
		cFrame->enableMenuItem(CAML_SEND, false);
//        cFrame->enableMenuItem(CAML_SEND_SEL, false);
		cFrame->enableMenuItem(CAML_INTERRUPT, false);
		cFrame->enableMenuItem(CAML_STOP, false);
		cFrame->enableMenuItem(CAML_CLEAROUTPUT, false);
	}
}
void CChildFrame::updateMenus(bool activating)
{
	cFrame->enableMenuItem(FILE_INCLUDE, activating);
	cFrame->enableMenuItem(FILE_SAVE, activating);
	cFrame->enableMenuItem(FILE_CLOSE, activating);
	cFrame->enableMenuItem(FILE_SAVEAS, activating);
	cFrame->enableMenuItem(FILE_SAVEASFORMATTED, activating);
	cFrame->enableMenuItem(FILE_PRINT, activating);
    
	updateUndoMenuTitle();
	updateRedoMenuTitle();
	cFrame->enableMenuItem(EDIT_PASTE, activating);
	cFrame->enableMenuItem(EDIT_SELECTALL, activating);
	updateCopyAndCutMenus();
	cFrame->enableMenuItem(EDIT_INDENT, activating);
    
	updateCamlMenu(activating);
	cFrame->updateOutputMenu(OutputMode);
    
	if (activating)
	{
		cFrame->checkMenuItem(EDIT_INDENTMODE, IndentWithTabs);
		cFrame->checkMenuItem(EDIT_INDENTAFTERIN, IndentAfterIn);
		cFrame->checkMenuItem(EDIT_INDENTFILTER, IndentFilters);
		cFrame->checkMenuItem(EDIT_INDENTOCAML, UseOCamlIndenter);
        
        cFrame->enableMenuItem(EDIT_REPLACE, true);
        cFrame->enableMenuItem(EDIT_FIND, true);
        
		cFrame->updateSplitViewMenu();
        
		cFrame->checkMenuItem(VIEW_INPUTONLY, SplitterViewMode == VIEW_INPUTONLY);
		cFrame->checkMenuItem(VIEW_OUTPUTONLY, SplitterViewMode == VIEW_OUTPUTONLY);
		cFrame->checkMenuItem(VIEW_BOTH, SplitterViewMode == VIEW_BOTH);
        
		cFrame->checkMenuItem(VIEW_WRAPINPUT, WrapInput);
		cFrame->checkMenuItem(VIEW_WRAPOUTPUT, WrapOutput);
		cFrame->checkMenuItem(VIEW_SYNTAXCOLOR, SyntaxColoring);
        
		cFrame->checkMenuItem(ENCODING_UNIX, PreferredEncoding == ENCODING_UNIX);
		cFrame->checkMenuItem(ENCODING_MAC, PreferredEncoding == ENCODING_MAC);
		cFrame->checkMenuItem(ENCODING_WIN, PreferredEncoding == ENCODING_WIN);
		cFrame->checkMenuItem(ENCODING_UTF8, PreferredEncoding == ENCODING_UTF8);
		cFrame->checkMenuItem(ENCODING_AUTO, AutomaticEncoding);
        
		cFrame->enableMenuItem(ENCODING_UNIX, !AutomaticEncoding);
		cFrame->enableMenuItem(ENCODING_MAC, !AutomaticEncoding);
		cFrame->enableMenuItem(ENCODING_WIN, !AutomaticEncoding);
		cFrame->enableMenuItem(ENCODING_UTF8, !AutomaticEncoding);
        
		cFrame->setStatus(0, textEdit->status());
        setStatus();
	}
	else
	{
		cFrame->setStatus(0, L"");
		cFrame->setStatus(1, L"");
	}
}
void CChildFrame::setStatus()
{
#ifdef _MSVC98_
    cFrame->setStatus(1, title + (isNewFile ? L"  (nouveau fichier)" : cInput->undoManager->getUndoType() == UR_NONE ? L" (enregistr\xE9)" : L" (non enregistr\xE9)"));
#else
    cFrame->setStatus(1, title + (isNewFile ? L"  (nouveau fichier)" : cInput->undoManager->getUndoType() == UR_NONE ? L" (enregistr\u00E9)" : L" (non enregistr\u00E9)"));
#endif
}

