//this file is part of notepad++
//Copyright (C)2003 Don HO ( donho@altern.org )
//
//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 <shlwapi.h>
#include "Notepad_plus.h"
#include "SysMsg.h"
#include "FileDialog.h"
#include "resource.h"
#include "printer.h"
#include "Process.h"
#include "FileNameStringSplitter.h"
#include "lesDlgs.h"

const char Notepad_plus::_className[32] = NOTEPAD_PP_CLASS_NAME;

void Notepad_plus::init(HINSTANCE hInst, HWND parent, const char *cmdLine)
{
    Window::init(hInst, parent);
    
    WNDCLASS MACOCS30EditorClass;

    MACOCS30EditorClass.style = 0;//CS_HREDRAW | CS_VREDRAW;
    MACOCS30EditorClass.lpfnWndProc = Notepad_plus_Proc;
    MACOCS30EditorClass.cbClsExtra = 0;
    MACOCS30EditorClass.cbWndExtra = 0;
    MACOCS30EditorClass.hInstance = _hInst;
    MACOCS30EditorClass.hIcon = ::LoadIcon(_hInst, MAKEINTRESOURCE(IDI_M30ICON));
    MACOCS30EditorClass.hCursor = NULL;
    MACOCS30EditorClass.hbrBackground = ::CreateSolidBrush(::GetSysColor(COLOR_MENU));
    MACOCS30EditorClass.lpszMenuName = MAKEINTRESOURCE(IDR_M30_MENU);
    MACOCS30EditorClass.lpszClassName = _className;

    if (!::RegisterClass(&MACOCS30EditorClass))
    {
        systemMessage("System Err");
        throw int(98);
    }

    _hSelf = ::CreateWindowEx(
                    WS_EX_ACCEPTFILES/*WS_EX_CLIENTEDGE*/,\
                    _className,\
                    "Notepad++",\
                    WS_OVERLAPPEDWINDOW    | WS_CLIPCHILDREN,\
                    CW_USEDEFAULT, CW_USEDEFAULT,\
                    CW_USEDEFAULT, CW_USEDEFAULT,\
                    _hParent,\
                    NULL,\
                    _hInst,\
                    (LPVOID)this); // pass the ptr of this instantiated object
                                   // for retrive it in Notepad_plus_Proc from
                                   // the CREATESTRUCT.lpCreateParams afterward.
  
    if (!_hSelf)
    {
        systemMessage("System Err");
        throw int(777);
    }

    if (cmdLine)
    {
        FileNameStringSplitter fnss(cmdLine);
        char *pFn = NULL;
        for (int i = 0 ; i < fnss.size() ; i++)
        {
            pFn = (char *)fnss.getFileName(i);
            doOpen((const char *)pFn);
        }
    }
    setTitle(_className);
    display();
    checkDocState();
}

bool Notepad_plus::doOpen(const char *fileName)
{
    int i = - 1;
    if ( (i = _pDocTab->find(fileName)) != -1)
    {
        setTitleWith(_pDocTab->activate(i));
        _pEditView->getFocus();
        return false;
    }

    bool isNewDoc2Close = false;
    FILE *fp = fopen(fileName, "rb");
    
    if (fp)
    {
        if ((_pEditView->getNbDoc() == 1)
            && Buffer::isUntitled(_pEditView->getCurrentTitle())
            && (!_pEditView->isCurrentDocDirty()) && (_pEditView->getCurrentDocLen() == 0))
        {
            //_pDocTab->closeCurrentDoc();
            isNewDoc2Close = true;
        }
        setTitleWith(_pDocTab->newDoc(fileName));

        // It's VERY IMPORTANT to reset the view
        _pEditView->execute(SCI_CLEARALL);

        const int blockSize = 128 * 1024;
        char data[blockSize];

        int lenFile = int(fread(data, 1, sizeof(data), fp));
        
        // 3 formats : WIN_FORMAT, UNIX_FORMAT and MAC_FORMAT
        (_pEditView->getCurrentBuffer()).determinateFormat(data);
        _pEditView->execute(SCI_SETEOLMODE, _pEditView->getCurrentBuffer().getFormat());

        while (lenFile > 0) {
            _pEditView->execute(SCI_ADDTEXT, lenFile, reinterpret_cast<LPARAM>(static_cast<char *>(data)));
            lenFile = int(fread(data, 1, sizeof(data), fp));
        }
        fclose(fp);

        //_pDocTab->activate(_pEditView->getCurrentDocIndex());
        _pEditView->getFocus();
        _pEditView->execute(SCI_SETSAVEPOINT);
        _pEditView->execute(EM_EMPTYUNDOBUFFER);

        // if file is read oly, we set the view read only
        _pEditView->execute(SCI_SETREADONLY, _pEditView->isCurrentBufReadOnly());
        if (isNewDoc2Close)
            _pDocTab->closeDocAt(0);

        // Then replace the caret to the begining
        _pEditView->execute(SCI_GOTOPOS, 0);

        return true;
    }
    else
    {
        char msg[MAX_PATH + 100];
        strcpy(msg, "Could not open file \"");
        //strcat(msg, fullPath);
        strcat(msg, fileName);
        strcat(msg, "\".");
        ::MessageBox(_hSelf, msg, "ERR", MB_OK);
        return false;
    }
}

void Notepad_plus::fileOpen()
{
    FileDialog fDlg(_hSelf, _hInst, true);
    
    fDlg.setExtFilter("All types", ".*", NULL);
    fDlg.setExtFilter("c/c++ src file", ".c", ".cpp", ".cxx", ".h", NULL);
    fDlg.setExtFilter("Window Resource File", ".rc", NULL);

    fDlg.setExtFilter("Java src file", ".java", NULL);
    fDlg.setExtFilter("HTML file", ".html", ".htm", NULL);
    fDlg.setExtFilter("XML file", ".xml", NULL);
    fDlg.setExtFilter("Makeile", "makefile", "GNUmakefile", ".makefile", NULL);
    fDlg.setExtFilter("php file", ".php", ".phtml", NULL);
    fDlg.setExtFilter("asp file", ".asp", NULL);
    fDlg.setExtFilter("ini file", ".ini", NULL);
    fDlg.setExtFilter("nfo file", ".nfo", NULL);
    fDlg.setExtFilter("VB/VBS file", ".vb", ".vbs", NULL);
    fDlg.setExtFilter("SQL file", ".sql", NULL);
    fDlg.setExtFilter("Objective C file", ".m", ".h", NULL);
    if (stringVector *pfns = fDlg.doOpenDlg())
    {
        int sz = int(pfns->size());
        for (int i = 0 ; i < sz ; i++)
            doOpen((pfns->at(i)).c_str());
    }
}

bool Notepad_plus::doSave(const char *filename)
{
    FILE *fp = fopen(filename, "wb");
    const int blockSize = 128 * 1024;
    if (fp)
    {
        char data[blockSize + 1];
        int lengthDoc = _pEditView->getCurrentDocLen();
        for (int i = 0; i < lengthDoc; i += blockSize)
        {
            int grabSize = lengthDoc - i;
            if (grabSize > blockSize)
                grabSize = blockSize;
            
            _pEditView->getText(data, i, i + grabSize);
            fwrite(data, grabSize, 1, fp);
        }
        fclose(fp);
        //checkIfReadOnlyFile()
        _pEditView->updateCurrentBufTimeStamp();
        _pEditView->execute(SCI_SETSAVEPOINT);
        return true;
    }
    return false;
}

bool Notepad_plus::fileSave()
{
    if (_pEditView->isCurrentDocDirty())
    {
        const char *fn = _pEditView->getCurrentTitle();
        return (Buffer::isUntitled(fn))?fileSaveAs():doSave(fn);
    }
    return false;
}

bool Notepad_plus::fileSaveAll() {

    int iCurrent = _pEditView->getCurrentDocIndex();

    if (_mainWindowStatus & TWO_VIEWS_MASK)
    {
        switchEditViewTo((getCurrentView() == MAIN_VIEW)?SUB_VIEW:MAIN_VIEW);
        int iCur = _pEditView->getCurrentDocIndex();

        for (int i = 0 ; i < _pEditView->getNbDoc() ; i++)
        {
            _pDocTab->activate(i);
            fileSave();
        }

        _pDocTab->activate(iCur);
        
        switchEditViewTo((getCurrentView() == MAIN_VIEW)?SUB_VIEW:MAIN_VIEW);
    }
    
    for (int i = 0 ; i < _pEditView->getNbDoc() ; i++)
    {
        _pDocTab->activate(i);
        fileSave();
    }

    _pDocTab->activate(iCurrent);
    return true;
}

bool Notepad_plus::fileSaveAs()
{
/*    FileDialog fDlg(_hSelf, _hInst, false);*/

    FileDialog fDlg(_hSelf, _hInst, false, styleSave);

    fDlg.setExtFilter("All types", ".*", NULL);

    fDlg.setExtFilter("c src file", ".c", NULL);
    fDlg.setExtFilter("c++ src file", ".cpp", NULL);
    fDlg.setExtFilter("Window Resource File", ".rc", NULL);
    fDlg.setExtFilter("c/c++ header file", ".h", NULL);
    fDlg.setExtFilter("Java src file", ".java", NULL);
    fDlg.setExtFilter("HTML file", ".html", NULL);
    fDlg.setExtFilter("XML file", ".xml", NULL);
    fDlg.setExtFilter("php file", ".php",NULL);
    fDlg.setExtFilter("ini file", ".ini", NULL);
    fDlg.setExtFilter("Normal text file", ".txt", NULL);

    if (char *pfn = fDlg.doSaveDlg())
    {
        int i = _pEditView->findDocIndexByName(pfn);
        if ((i == -1) || (i == _pEditView->getCurrentDocIndex()))
        {
            doSave(pfn);
            _pEditView->setCurrentTitle(pfn);
            _pEditView->setCurrentDocReadOnly(false);
            _pEditView->execute(SCI_SETREADONLY, false);
            _pDocTab->updateCurrentTabItem(PathFindFileName(pfn));
            setTitleWith(pfn);
            return true;
        }
        else
        {
            ::MessageBox(_hSelf, "The file is already opened in the Notepad++.", "ERROR", MB_OK | MB_ICONSTOP);
            _pDocTab->activate(i);
            return false;
        }
        checkModifiedDocument();
    }
    else // cancel button is pressed
    {
        checkModifiedDocument();
        return false;
    }
}

void Notepad_plus::filePrint(bool showDialog)
{
    Printer printer;

    int startPos = int(_pEditView->execute(SCI_GETSELECTIONSTART));
    int endPos = int(_pEditView->execute(SCI_GETSELECTIONEND));
    
    printer.init(_hInst, _hSelf, showDialog, startPos, endPos);
    printer.doPrint(*_pEditView);
}

void Notepad_plus::enableCommand(int cmdID, bool doEnable, int which) const
{
    if (which & MENU)
    {
        enableMenu(cmdID, doEnable);
    }
    if (which & TOOLBAR)
    {
        _toolBar.enable(cmdID, doEnable);
    }
}

void Notepad_plus::checkClipboard()
{
    bool hasSelection = _pEditView->execute(SCI_GETSELECTIONSTART) != _pEditView->execute(SCI_GETSELECTIONEND);
    bool canPaste = bool(_pEditView->execute(SCI_CANPASTE));
    enableCommand(IDM_EDIT_CUT, hasSelection, MENU | TOOLBAR);
    enableCommand(IDM_EDIT_COPY, hasSelection, MENU | TOOLBAR);
    enableCommand(IDM_EDIT_PASTE, canPaste, MENU | TOOLBAR);
}

void Notepad_plus::checkDocState()
{
    bool isCurrentDirty = _pEditView->isCurrentDocDirty();
    bool isSeveralDirty = !_pEditView->isAllDocsClean();
    enableCommand(IDM_FILE_SAVE, isCurrentDirty, MENU | TOOLBAR);
    enableCommand(IDM_FILE_SAVEALL, isSeveralDirty, MENU | TOOLBAR);
    enableConvertMenuItems((_pEditView->getCurrentBuffer()).getFormat());
    checkLangsMenu(-1);
}

void Notepad_plus::checkUndoState()
{
    enableCommand(IDM_EDIT_UNDO, (bool)_pEditView->execute(SCI_CANUNDO), MENU | TOOLBAR);
    enableCommand(IDM_EDIT_REDO, (bool)_pEditView->execute(SCI_CANREDO), MENU | TOOLBAR);
}

void Notepad_plus::synchronise()
{
    Buffer & bufSrc = _pEditView->getCurrentBuffer();
    
    const char *fn = bufSrc.getFileName();

    int i = getNonCurrentDocTab()->find(fn);
    if (i != -1)
    {
        Buffer & bufDest = getNonCurrentEditView()->getBufferAt(i);
        bufDest.synchroniseWith(bufSrc);
        getNonCurrentDocTab()->updateTabItem(i);
    }
}

void Notepad_plus::setLangStatus(LangType langType)
{
    std::string str2Show;

    switch (langType)
    {
    case L_C:
        str2Show = "c source file";
        break;

    case L_H:
        str2Show = "c or c++ header file";
        break;

    case L_CPP:
        str2Show = "c++ source file";
        break;

    case L_OBJC:
        str2Show = "Objective C source file";
        break;

    case L_JAVA:
        str2Show = "Java source file";
        break;

    case L_RC :
        str2Show = "Windows Resource file";
        break;
    
    case L_MAKEFILE:
        str2Show = "Makefile";
        break;

    case L_HTML:
        str2Show = "Hyper Text Markup Language File";
        break;

    case L_XML:
        str2Show = "eXtensible Markup Language File";
        break;

    case L_PHP:
        str2Show = "php File";
        break;

    case L_ASP:
        str2Show = "asp File";
        break;

    case L_NFO:
        str2Show = "M$ Dos Style";
        break;

    case L_USER:
        str2Show = "User Define File";
        break;

    case L_SQL:
        str2Show = "SQL File";
        break;

    case L_VB:
        str2Show = "Visual Basic File";
        break;

    case L_M30 :
        str2Show = "Macocs Script File";
        break;
    
    case L_PCOM:
        str2Show = "PCOM Script File";
        break;
    default:
        str2Show = "Normal text File";

    }
    _statusBar.setText(str2Show.c_str(), 0);
}

void Notepad_plus::notify(SCNotification *notification)
{
  switch (notification->nmhdr.code)
  {
    case SCN_DOUBLECLICK :
        //MessageBox(NULL, "DBL click", "SCN_DOUBLECLICK", MB_OK);
      break;

    case SCN_SAVEPOINTREACHED:
      _pEditView->setCurrentDocState(false);
      _pDocTab->updateCurrentTabItem();
      checkDocState();
      synchronise();
      break;

    case SCN_SAVEPOINTLEFT:
      _pEditView->setCurrentDocState(true);
      _pDocTab->updateCurrentTabItem();
      checkDocState();
      synchronise();
      break;
    
    case  SCN_MODIFYATTEMPTRO :
      // on fout rien
      break;
    
    case SCN_KEY:
      //MessageBox(NULL, "Putain, sa mere!", "toto", MB_OK);
      break;

    case TCN_TABDROPPEDOUTSIDE:
    case TCN_TABDROPPED:
    {
        TabBar *sender = reinterpret_cast<TabBar *>(notification->nmhdr.idFrom);
        int destIndex = sender->getTabDraggedIndex();
        int scrIndex  = sender->getSrcTabIndex();

        // if the dragNdrop tab is not the current view tab,
        // we have to set it to the current view tab
        if (notification->nmhdr.hwndFrom != _pDocTab->getHSelf())
            switchEditViewTo((getCurrentView() == MAIN_VIEW)?SUB_VIEW:MAIN_VIEW);

        _pEditView->sortBuffer(destIndex, scrIndex);
        _pEditView->setCurrentIndex(destIndex);

        if (notification->nmhdr.code == TCN_TABDROPPEDOUTSIDE)
        {
            POINT p = sender->getDraggingPoint();

            //It's the coordinate of screen, so we can call
            //"WindowFromPoint" function without converting the point
            HWND hWin = ::WindowFromPoint(p);
            if (hWin == _pEditView->getHSelf()) // In the same view group
            {
                // If there's only one view...
                //if (!(_mainWindowStatus & TWO_VIEWS_MASK))
                {
                    
                    if (!_hTabPopupDropMenu)
                    {
                        _hTabPopupDropMenu = ::CreatePopupMenu();
                        ::InsertMenu(_hTabPopupDropMenu, 0, MF_BYPOSITION, IDC_DOC_GOTO_ANOTHER_VIEW, "Go to another View");
                        ::InsertMenu(_hTabPopupDropMenu, 1, MF_BYPOSITION, IDC_DOC_CLONE_TO_ANOTHER_VIEW, "Clone to another View");
                    }
                    ::TrackPopupMenu(_hTabPopupDropMenu, TPM_LEFTALIGN, p.x, p.y, 0, _hSelf, NULL);
                }
            }
            else if ((hWin == getNonCurrentDocTab()->getHSelf()) ||
                     (hWin == getNonCurrentEditView()->getHSelf())) // In the another view group
            {
                if (::GetKeyState(VK_LCONTROL) & 0x80000000)
                    docGotoAnotherEditView(MODE_CLONE);
                else
                    docGotoAnotherEditView(MODE_TRANSFER);
            }
            //else on fout rien!!! // It's non view group
                //::MessageBox(NULL, "chez qqn d'autre", "", MB_OK);
        }
        break;
    }

    case TCN_SELCHANGE:
    {
        char *fullPath = NULL;

        if (notification->nmhdr.hwndFrom == _mainDocTab.getHSelf())
        {
            fullPath = _mainDocTab.clickedUpdate();
            switchEditViewTo(MAIN_VIEW);
            
        }
        else if (notification->nmhdr.hwndFrom == _subDocTab.getHSelf())
        {
            fullPath = _subDocTab.clickedUpdate();
            switchEditViewTo(SUB_VIEW);
        }
        checkDocState();
        break;
    }

    case NM_CLICK :
    {        
        if (notification->nmhdr.hwndFrom == _statusBar.getHSelf())
        {
            LPNMMOUSE lpnm = (LPNMMOUSE)notification;
            if (lpnm->dwItemSpec == 3)
            {
                bool isOverTypeMode = _pEditView->execute(SCI_GETOVERTYPE);
                _pEditView->execute(SCI_SETOVERTYPE, !isOverTypeMode);
                _statusBar.setText((_pEditView->execute(SCI_GETOVERTYPE))?"OVR":"INS", 3);
            }
        }
        break;
    }

    case NM_DBLCLK :
    {        
        if (notification->nmhdr.hwndFrom == _statusBar.getHSelf())
        {
            LPNMMOUSE lpnm = (LPNMMOUSE)notification;
            if (lpnm->dwItemSpec == 1)
            {
                _goToLineDlg.doDialog();
            }
        }
        break;
    }

    case NM_RCLICK :
    {        
        if (notification->nmhdr.hwndFrom == _mainDocTab.getHSelf())
        {
            switchEditViewTo(MAIN_VIEW);
        }
        else if (notification->nmhdr.hwndFrom == _subDocTab.getHSelf())
        {
            switchEditViewTo(SUB_VIEW);
        }
        else // From tool bar or Status Bar
            break;
        
        POINT p, clientPoint;
        ::GetCursorPos(&p);
        clientPoint.x = p.x;
        clientPoint.y = p.y;
        
        if (!_hTabPopupMenu)
        {
            _hTabPopupMenu = ::CreatePopupMenu();
            ::InsertMenu(_hTabPopupMenu, 0, MF_BYPOSITION, IDM_FILE_CLOSE, "Close me");
            ::InsertMenu(_hTabPopupMenu, 1, MF_BYPOSITION, IDM_FILE_CLOSEALL_BUT_CURRENT, "Close all but me");
            ::InsertMenu(_hTabPopupMenu, 2, MF_BYPOSITION, IDM_FILE_SAVE, "Save me");
            ::InsertMenu(_hTabPopupMenu, 3, MF_BYPOSITION, IDM_FILE_SAVEAS, "Save me As...");
            ::InsertMenu(_hTabPopupMenu, 4, MF_BYPOSITION, IDM_FILE_PRINT, "Print me");
            
            ::InsertMenu(_hTabPopupMenu, 5, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
            ::InsertMenu(_hTabPopupMenu, 6, MF_BYPOSITION, IDC_DOC_GOTO_ANOTHER_VIEW, "Go to another View");
            ::InsertMenu(_hTabPopupMenu, 7, MF_BYPOSITION, IDC_DOC_CLONE_TO_ANOTHER_VIEW, "Clone to another View");
        }


        //verifyPopMenuItem();
        ScreenToClient(_pDocTab->getHSelf(), &clientPoint);
        ::SendMessage(_pDocTab->getHSelf(), WM_LBUTTONDOWN, 0, MAKELONG(clientPoint.x, clientPoint.y));
        ::TrackPopupMenu(_hTabPopupMenu, TPM_LEFTALIGN, p.x, p.y, 0, _hSelf, NULL);
        break;
    }

    case SCN_MARGINCLICK:
    {
        if (notification->nmhdr.hwndFrom == _mainEditView.getHSelf())
            switchEditViewTo(MAIN_VIEW);
            
        else if (notification->nmhdr.hwndFrom == _subEditView.getHSelf())
            switchEditViewTo(SUB_VIEW);
        
        if (notification->margin == ScintillaEditView::_SC_MARGE_FOLDER)
        {
            _pEditView->marginClick(notification->position, notification->modifiers);
        }
        else if (notification->margin == ScintillaEditView::_SC_MARGE_SYBOLE)
        {
            
            int lineClick = int(_pEditView->execute(SCI_LINEFROMPOSITION, notification->position));
            bookmarkToggle(lineClick);
        
        }
        case SCN_CHARADDED:
            charAdded(static_cast<char>(notification->ch));
            break;
    }
    break;

    case SCN_UPDATEUI:
        braceMatch();
        updateStatusBar();
        break;

    case TTN_GETDISPINFO:
    {
        LPTOOLTIPTEXT lpttt;

        lpttt = (LPTOOLTIPTEXT)notification;
        lpttt->hinst = _hInst;

        // Specify the resource identifier of the descriptive
        // text for the given button.
        int idButton = lpttt->hdr.idFrom;
        switch (idButton)
        {
            case IDM_FILE_NEW:
                lpttt->lpszText = "New document";
                break;
            case IDM_FILE_OPEN:
                lpttt->lpszText = "Open file";
                break;
            case IDM_FILE_SAVE:
                lpttt->lpszText = "Save current file";
                break;
            case IDM_FILE_SAVEALL:
                lpttt->lpszText = "Save all files";
                break;
            case IDM_FILE_CLOSE:
                lpttt->lpszText = "Close current file";
                break;
            case IDM_FILE_CLOSEALL:
                lpttt->lpszText = "Close all files";
                break;
            case IDM_EDIT_CUT:
                lpttt->lpszText = "Cut";
                break;
            case IDM_EDIT_COPY:
                lpttt->lpszText = "Copy";
                break;
            case IDM_EDIT_PASTE:
                lpttt->lpszText = "Paste";
                break;
            case IDM_EDIT_UNDO:
                lpttt->lpszText = "Undo";
                break;
            case IDM_EDIT_REDO:
                lpttt->lpszText = "Redo";
                break;
            case IDM_SEARCH_FIND:
                lpttt->lpszText = "Find...";
                break;
            case IDM_SEARCH_REPLACE:
                lpttt->lpszText = "Replace...";
                break;
            case IDM_VIEW_ZOOMIN:
                lpttt->lpszText = "Zoom in";
                break;
            case IDM_VIEW_ZOOMOUT:
                lpttt->lpszText = "Zoom out";
                break;
            case IDM_VIEW_WRAP:
                lpttt->lpszText = "Wrap text";
                break;
            case IDM_VIEW_ALL_CHARACTERS:
                lpttt->lpszText = "Invisible characters";
                break;
            case IDM_VIEW_INDENT_GUIDE:
                lpttt->lpszText = "View/Unview indent guideline";
                break;
            case IDM_VIEW_USER_DLG:
                lpttt->lpszText = "Toggle customizable color pannel";
                break;
            case IDC_BUTTON_PRINT:
                lpttt->lpszText = "Print current document";
                break;

        }
        break;
    }
    break;

    case SCN_ZOOM:
        _pEditView->setLineNumberWidth(_pEditView->hasMarginShowed(ScintillaEditView::_SC_MARGE_LINENUMBER));
        break;

    default :
        break;

  }
  //return TRUE;
}
void Notepad_plus::findMatchingBracePos(int & braceAtCaret, int & braceOpposite)
{
    int caretPos = _pEditView->execute(SCI_GETCURRENTPOS, 0, 0);
    braceAtCaret = -1;
    braceOpposite = -1;
    char charBefore = '\0';
    char styleBefore = '\0';
    int lengthDoc = _pEditView->execute(SCI_GETLENGTH, 0, 0);

    if ((lengthDoc > 0) && (caretPos > 0))
    {
        charBefore = _pEditView->execute(SCI_GETCHARAT, caretPos - 1, 0);
    }
    // Priority goes to character before caret
    if (charBefore && strchr("[](){}", charBefore))
    {
        braceAtCaret = caretPos - 1;
    }

    if (lengthDoc > 0  && (braceAtCaret < 0))
    {
        // No brace found so check other side
        char charAfter = _pEditView->execute(SCI_GETCHARAT, caretPos, 0);
        if (charAfter && strchr("[](){}", charAfter))
        {
            braceAtCaret = caretPos;
        }
    }
    if (braceAtCaret >= 0)
        braceOpposite = _pEditView->execute(SCI_BRACEMATCH, braceAtCaret, 0);
}

void Notepad_plus::braceMatch()
{
    //if (!bracesCheck)
        //return;
    int braceAtCaret = -1;
    int braceOpposite = -1;
    findMatchingBracePos(braceAtCaret, braceOpposite);

    if ((braceAtCaret != -1) && (braceOpposite == -1))
    {
        _pEditView->execute(SCI_BRACEBADLIGHT, braceAtCaret);
        _pEditView->execute(SCI_SETHIGHLIGHTGUIDE);
    }
    else
    {
        _pEditView->execute(SCI_BRACEHIGHLIGHT, braceAtCaret, braceOpposite);

        if (_pEditView->isShownIndentGuide())
        {
            int columnAtCaret = _pEditView->execute(SCI_GETCOLUMN, braceAtCaret);
            int columnOpposite = _pEditView->execute(SCI_GETCOLUMN, braceOpposite);
            _pEditView->execute(SCI_SETHIGHLIGHTGUIDE, min(columnAtCaret, columnOpposite));
        }
    }
}

void Notepad_plus::charAdded(char chAdded)
{
    //if (indentMaintain)
        MaintainIndentation(chAdded);
}

void Notepad_plus::MaintainIndentation(char ch) {
    int eolMode = _pEditView->execute(SCI_GETEOLMODE);
    int curLine = _pEditView->getCurrentLineNumber();
    int lastLine = curLine - 1;
    int indentAmount = 0;

    if (((eolMode == SC_EOL_CRLF || eolMode == SC_EOL_LF) && ch == '\n') ||
            (eolMode == SC_EOL_CR && ch == '\r'))
    {
        //if (props.GetInt("indent.automatic")) {
            while (lastLine >= 0 && _pEditView->getLineLength(lastLine) == 0)
                lastLine--;
        //}
        if (lastLine >= 0) {
            indentAmount = _pEditView->getLineIndent(lastLine);
        }
        if (indentAmount > 0) {
            _pEditView->setLineIndent(curLine, indentAmount);
        }
    }
}

void Notepad_plus::command(int id)
{
    switch (id)
    {
        case IDM_FILE_NEW:
            fileNew();
            break;
        
        case IDM_FILE_OPEN:
            fileOpen();
            break;

        case IDM_FILE_CLOSE:
            fileClose();
            break;

        case IDM_FILE_CLOSEALL:
            fileCloseAll();
            break;

        case IDM_FILE_CLOSEALL_BUT_CURRENT :
            fileCloseAllButCurrent();
            break;

        case IDM_FILE_SAVE :
            fileSave();
            break;

        case IDM_FILE_SAVEALL :
            fileSaveAll();
            break;

        case IDM_FILE_SAVEAS :
            fileSaveAs();
            break;

        case IDC_BUTTON_PRINT :
            filePrint(false);
            break;

        case IDM_FILE_PRINT :
            filePrint(true);
            break;

        case IDM_FILE_ASIAN_LANG :
            _pEditView->execute(SCI_SETCODEPAGE,  SC_CP_UTF8);
            break;

        case IDM_FILE_EXIT:
            ::SendMessage(_hSelf, WM_CLOSE, 0, 0);
            break;

        case IDM_EDIT_UNDO:
            _pEditView->execute(WM_UNDO);
            checkClipboard();
            checkUndoState();
            break;

        case IDM_EDIT_REDO:
            _pEditView->execute(SCI_REDO);
            checkClipboard();
            checkUndoState();
            break;

        case IDM_EDIT_CUT:
            _pEditView->execute(WM_CUT);
            break;

        case IDM_EDIT_COPY:
            _pEditView->execute(WM_COPY);
            checkClipboard();
            break;

        case IDM_EDIT_PASTE:
            _pEditView->execute(WM_PASTE);
            break;

        case IDM_EDIT_DELETE:
            _pEditView->execute(WM_CLEAR);
            break;

        case IDM_SEARCH_FIND :
        case IDM_SEARCH_REPLACE :
        {
            const int strSize = 256;
            char str[strSize];
            if (_pEditView->getSelectedText(str, strSize))
            {
                _findReplaceDlg.doDialog((id == IDM_SEARCH_FIND)?FIND:REPLACE);
                _findReplaceDlg.setSearchText(str);
            }
            else
                ::MessageBox(_hSelf, "can not search over 256 characters", "error", MB_OK);
            break;
        }

        case IDM_SEARCH_FINDNEXT :
            _findReplaceDlg.processFindNext();
            break;

        
        case IDM_SEARCH_GOTOLINE :
        {
            _goToLineDlg.doDialog();
            break;
        }

        case IDM_SEARCH_TOGGLE_BOOKMARK :
            bookmarkToggle(-1);
            break;

        case IDM_SEARCH_NEXT_BOOKMARK:
            bookmarkNext(true);
            break;

        case IDM_SEARCH_PREV_BOOKMARK:
            bookmarkNext(false);
            break;

        case IDM_SEARCH_CLEAR_BOOKMARKS:
            bookmarkClearAll();
            break;
            
        case IDM_VIEW_USER_DLG :
        {
            bool isUDDlgVisible = false;
                
            UserDefineDialog *udd = _pEditView->getUserDefineDlg();
            if (!udd->isCreated())
            {
                _pEditView->doUserDefineDlg();
                // the 1st time isUDDlgVisible should be false
            }
            else
            {
                isUDDlgVisible = udd->isVisible();
                
                bool isUDDlgDocked = udd->isDocked();
                if ((isUDDlgDocked)&&(isUDDlgVisible))
                {
                    ::ShowWindow(_pMainSplitter->getHSelf(), SW_HIDE);

                    if (_mainWindowStatus & TWO_VIEWS_MASK)
                        _pMainWindow = &_subSplitter;
                    else
                        _pMainWindow = _pDocTab;

                    RECT rc;
                    getMainClientRect(rc);
                    _pMainWindow->reSizeTo(rc);
                    
                    udd->display(false);
                    _mainWindowStatus &= ~DOCK_MASK;
                }
                else if ((isUDDlgDocked)&&(!isUDDlgVisible))
                {
                    if (!_pMainSplitter)
                    {
                        _pMainSplitter = new SplitterContainer;
                        _pMainSplitter->init(_hInst, _hSelf);

                        Window *pWindow;
                        if (_mainWindowStatus & TWO_VIEWS_MASK)
                            pWindow = &_subSplitter;
                        else
                            pWindow = _pDocTab;

                        _pMainSplitter->create(pWindow, ScintillaEditView::getUserDefineDlg(), 8, RIGHT_FIX, 45);
                    }

                    _pMainWindow = _pMainSplitter;

                    _pMainSplitter->setWin0((_mainWindowStatus & TWO_VIEWS_MASK)?(Window *)&_subSplitter:(Window *)_pDocTab);

                    RECT rc;
                    getMainClientRect(rc);
                    _pMainWindow->reSizeTo(rc);
                    _pMainWindow->display();

                    _mainWindowStatus |= DOCK_MASK;
                }
                else if ((!isUDDlgDocked)&&(isUDDlgVisible))
                {
                    udd->display(false);
                }
                else //((!isUDDlgDocked)&&(!isUDDlgVisible))
                    udd->display();
            }
            checkMenuItem(IDM_VIEW_USER_DLG, !isUDDlgVisible);
            _toolBar.setCheck(IDM_VIEW_USER_DLG, !isUDDlgVisible);

            break;
        }

        case IDM_EDIT_SELECTALL:
            _pEditView->execute(SCI_SELECTALL);
            checkClipboard();
            break;

        case IDM_VIEW_TOOLBAR_HIDE:
        {
            int checkedID = getToolBarState();

            if (checkedID != IDM_VIEW_TOOLBAR_HIDE)
            {
                RECT rc;
                getClientRect(rc);
                _toolBar.display(false);
                ::SendMessage(_hSelf, WM_SIZE, SIZE_RESTORED, MAKELONG(rc.bottom, rc.right));
                checkToolBarMenu(id);
            }
        }
        break;

        case IDM_VIEW_TOOLBAR_REDUCE:
        {
            int checkedID = getToolBarState();

            if (checkedID != IDM_VIEW_TOOLBAR_REDUCE)
            {
                RECT rc;
                getClientRect(rc);
                _toolBar.reduce();
                _toolBar.display();
                ::SendMessage(_hSelf, WM_SIZE, SIZE_RESTORED, MAKELONG(rc.bottom, rc.right));
                checkToolBarMenu(id);
            }
        }
        break;

        case IDM_VIEW_TOOLBAR_ENLARGE:
        {
            int checkedID = getToolBarState();
            if (checkedID != IDM_VIEW_TOOLBAR_ENLARGE)
            {
                RECT rc;
                getClientRect(rc);
                _toolBar.enlarge();
                _toolBar.display();
                ::SendMessage(_hSelf, WM_SIZE, SIZE_RESTORED, MAKELONG(rc.bottom, rc.right));
                checkToolBarMenu(id);
            }
            break;
        }
        
        case IDM_VIEW_LOCKTABBAR:
        {
            bool isDrag = TabBar::doDragNDropOrNot();
            TabBar::doDragNDrop(!isDrag);
            checkMenuItem(IDM_VIEW_LOCKTABBAR, isDrag);
            break;
        }

        case IDM_VIEW_DRAWTABBAR_INACIVETAB:
        case IDM_VIEW_DRAWTABBAR_TOPBAR:
        {
            bool drawIt = (id == IDM_VIEW_DRAWTABBAR_TOPBAR)?TabBar::drawTopBar():TabBar::drawInactiveTab();
            if (id == IDM_VIEW_DRAWTABBAR_TOPBAR)
                TabBar::setDrawTopBar(!drawIt);
            else
                TabBar::setDrawInactiveTab(!drawIt);

            checkMenuItem(id, !drawIt);
            break;
        }

        case IDM_VIEW_STATUSBAR:
            RECT rc;
            getClientRect(rc);
            _statusBar.display((bool)checkStatusBar());
            ::SendMessage(_hSelf, WM_SIZE, SIZE_RESTORED, MAKELONG(rc.bottom, rc.right));
            break;

        case IDM_VIEW_LINENUMBER:
        case IDM_VIEW_SYMBOLMARGIN:
        case IDM_VIEW_FOLDERMAGIN:
        {
            int margin;
            if (id == IDM_VIEW_LINENUMBER)
                margin = ScintillaEditView::_SC_MARGE_LINENUMBER;
            else if (id == IDM_VIEW_SYMBOLMARGIN)
                margin = ScintillaEditView::_SC_MARGE_SYBOLE;
            else
                margin = ScintillaEditView::_SC_MARGE_FOLDER;

            if (_pEditView->hasMarginShowed(margin))
                _pEditView->showMargin(margin, false);
            else
                _pEditView->showMargin(margin);

            checkMenuItem(id, _pEditView->hasMarginShowed(margin));
            break;
        }

        case IDM_VIEW_FOLDERMAGIN_SIMPLE:
        case IDM_VIEW_FOLDERMAGIN_ARROW:
        case IDM_VIEW_FOLDERMAGIN_CIRCLE:
        case IDM_VIEW_FOLDERMAGIN_BOX:
        {
            int checkedID = getFolderMarginStyle();
            if (checkedID == id) return;
            folderStyle fStyle = (id == IDM_VIEW_FOLDERMAGIN_SIMPLE)?FOLDER_STYLE_SIMPLE:\
                ((id == IDM_VIEW_FOLDERMAGIN_ARROW)?FOLDER_STYLE_ARROW:\
                ((id == IDM_VIEW_FOLDERMAGIN_CIRCLE)?FOLDER_STYLE_CIRCLE:FOLDER_STYLE_BOX));
            _pEditView->setMakerStyle(fStyle);
            checkFolderMarginStyleMenu(id);
            break;
        }
        case IDM_VIEW_ALL_CHARACTERS:
        {
            HMENU hMenu = ::GetMenu(_hSelf);
            bool isChecked = (::GetMenuState(hMenu, IDM_VIEW_ALL_CHARACTERS, MF_BYCOMMAND) == MF_CHECKED);
            _pEditView->showInvisibleChars(!isChecked);

            _toolBar.setCheck(IDM_VIEW_ALL_CHARACTERS, !_toolBar.getCheckState(IDM_VIEW_ALL_CHARACTERS));
            ::CheckMenuItem(hMenu, IDM_VIEW_ALL_CHARACTERS, MF_BYCOMMAND | (isChecked?MF_UNCHECKED:MF_CHECKED));
            break;
        }
            
        case IDM_VIEW_INDENT_GUIDE:
        {
            _pEditView->showIndentGuideLine(!_pEditView->isShownIndentGuide());
            _toolBar.setCheck(IDM_VIEW_INDENT_GUIDE, _pEditView->isShownIndentGuide());
            checkMenuItem(IDM_VIEW_INDENT_GUIDE, _pEditView->isShownIndentGuide());
            break;
        }

        case IDM_VIEW_CURLINE_HILITING:
        {
            COLORREF colour = (NppParameters::getInstance())->getCurLineHilitingColour();
            _pEditView->setCurrentLineHiLiting(!_pEditView->isCurrentLineHiLiting(), colour);
            checkMenuItem(IDM_VIEW_CURLINE_HILITING, _pEditView->isCurrentLineHiLiting());
            break;
        }

        case IDM_VIEW_WRAP:
        {
            _pEditView->wrap(!_pEditView->isWrap());
            _toolBar.setCheck(IDM_VIEW_WRAP, _pEditView->isWrap());
            checkMenuItem(IDM_VIEW_WRAP, _pEditView->isWrap());
            break;
        }

        case IDM_VIEW_ZOOMIN:
            {
            _pEditView->execute(SCI_ZOOMIN);
            break;
            }
        case IDM_VIEW_ZOOMOUT:
            _pEditView->execute(SCI_ZOOMOUT);
            break;


        case IDM_EXECUTE:
            _runDlg.doDialog();
            break;

/*
        case IDC_DOCK_USERDEFINE_DLG :
            break;

        case IDC_UNDOCK_USERDEFINE_DLG :
            break;
*/
        case IDM_FORMAT_TODOS :
        case IDM_FORMAT_TOUNIX :
        case IDM_FORMAT_TOMAC :
        {
            int f = int((id == IDM_FORMAT_TODOS)?SC_EOL_CRLF:(id == IDM_FORMAT_TOUNIX)?SC_EOL_LF:SC_EOL_CR);
            _pEditView->execute(SCI_SETEOLMODE, f);
            _pEditView->execute(SCI_CONVERTEOLS, f);
            (_pEditView->getCurrentBuffer()).setFormat((formatType)f);
            enableConvertMenuItems((formatType)f);
            setDisplayFormat((formatType)f);
            break;
        }
        
            _pEditView->execute(SCI_CONVERTEOLS, SC_EOL_LF);
            enableConvertMenuItems((_pEditView->getCurrentBuffer()).getFormat());
            break;

        
            _pEditView->execute(SCI_CONVERTEOLS, SC_EOL_CR);
            enableConvertMenuItems((_pEditView->getCurrentBuffer()).getFormat());
            break;

        case IDM_SETTING_TAB_SIZE:
        {
            ValueDlg tabSizeDlg;
            NppGUI & nppgui = (NppGUI &)((NppParameters::getInstance())->getNppGUI());
            tabSizeDlg.init(_hInst, _hSelf, nppgui._tabSize, "Tab Size : ");
            POINT p;
            ::GetCursorPos(&p);
            ::ScreenToClient(_hParent, &p);
            int size = tabSizeDlg.doDialog(p);
            if (size != -1)
            {
                nppgui._tabSize = size;
                _pEditView->execute(SCI_SETTABWIDTH, nppgui._tabSize);
            }

            break;
        }

        case IDM_SETTING_TAB_REPLCESPACE:
        {
            NppGUI & nppgui = (NppGUI &)((NppParameters::getInstance())->getNppGUI());
            nppgui._tabReplacedBySpace = !nppgui._tabReplacedBySpace;
            _pEditView->execute(SCI_SETUSETABS, !nppgui._tabReplacedBySpace);
            checkMenuItem(IDM_SETTING_TAB_REPLCESPACE, nppgui._tabReplacedBySpace);
            break;
        }

        case IDM_SETTING_HISTORY_SIZE :
        {
            ValueDlg nbHistoryDlg;
            NppParameters *pNppParam = NppParameters::getInstance();
            nbHistoryDlg.init(_hInst, _hSelf, pNppParam->getNbMaxFile(), "Max File : ");
            POINT p;
            ::GetCursorPos(&p);
            ::ScreenToClient(_hParent, &p);
            int size = nbHistoryDlg.doDialog(p);
            if (size != -1)
            {
                if (size > NB_MAX_FILE)
                    size = NB_MAX_FILE;
                pNppParam->setNbMaxFile(size);
            }
            break;
        }

        case IDC_DOC_GOTO_ANOTHER_VIEW:
            docGotoAnotherEditView(MODE_TRANSFER);
            break;

        case IDC_DOC_CLONE_TO_ANOTHER_VIEW:
            docGotoAnotherEditView(MODE_CLONE);
            break;

        case IDM_ABOUT:
            _aboutDlg.doDialog();
            break;
// WebControl bug
            /*
        case IDM_TRY :
        {
            int textLen = _pEditView->getCurrentDocLen();
            char *htmlStr = new char[textLen];
            _pEditView->getText(htmlStr, textLen);
            _webBrowser.displayStr(htmlStr);
            _webBrowser.display();
            delete [] htmlStr;
            break;
        }
            */
        case IDM_LANGSTYLE_CONFIG_DLG :
            _configStyleDlg.doDialog();
            break;

        case IDM_LANG_C    :
            setLanguage(id, L_C);
            break;

        case IDM_LANG_CPP :
            setLanguage(id, L_CPP);
            break;

        case IDM_LANG_JAVA :
            setLanguage(id, L_JAVA);
            break;

        case IDM_LANG_HTML :
            setLanguage(id, L_HTML);
            break;

        case IDM_LANG_XML :
            setLanguage(id, L_XML);
            break;

        case IDM_LANG_PHP :
            setLanguage(id, L_PHP);
            break;

        case IDM_LANG_ASP :
            setLanguage(id, L_ASP);
            break;

        case IDM_LANG_OBJC :
            setLanguage(id, L_OBJC);
            break;

        case IDM_LANG_VB :
            setLanguage(id, L_VB);
            break;

        case IDM_LANG_SQL :
            setLanguage(id, L_SQL);
            break;

        case IDM_LANG_ASCII :
            setLanguage(id, L_NFO);
            break;

        case IDM_LANG_USER :
            setLanguage(id, L_USER);
            break;

        case IDM_LANG_TEXT :
            setLanguage(id, L_TXT);
            break;

        case IDM_LANG_RC :
            setLanguage(id, L_RC);
            break;

        case IDM_LANG_MAKEFILE :
            setLanguage(id, L_MAKEFILE);
            break;

        case IDM_LANG_INI :
            setLanguage(id, L_INI);
            break;

        case IDC_PREV_DOC :
            activateNextDoc(dirUp);
            break;

        case IDC_NEXT_DOC :
            activateNextDoc(dirDown);
            break;

        default :
            if (id > IDM_FILE_EXIT && id < (IDM_FILE_EXIT + _nbLRFile + 1))
            {
                char fn[256];
                ::GetMenuString(::GetMenu(_hSelf), id, fn, sizeof(fn), MF_BYCOMMAND);
                if (!doOpen(fn))
                {
                    ::RemoveMenu(::GetMenu(_hSelf), id , MF_BYCOMMAND);
                }
            }
    }
}

void Notepad_plus::setTitleWith(const char *filePath)
{
    if (!filePath || !strcmp(filePath, ""))
        return;

    char str2concat[MAX_PATH];
    strcat(strcpy(str2concat, _className), " - ");
    strcat(str2concat, filePath);
    ::SetWindowText(_hSelf, str2concat);
}

void Notepad_plus::dropFiles(HDROP hdrop)
{
    if (hdrop)
    {
        // Determinate in which view the file(s) is (are) dropped
        POINT p;
        ::DragQueryPoint(hdrop, &p);
        HWND hWin = ::ChildWindowFromPoint(_hSelf, p);
        if (hWin)
        {
            if ((_mainEditView.getHSelf() == hWin) || (_mainDocTab.getHSelf() == hWin))
                switchEditViewTo(MAIN_VIEW);
            else if ((_subEditView.getHSelf() == hWin) || (_subDocTab.getHSelf() == hWin))
                switchEditViewTo(SUB_VIEW);
        }

        int filesDropped = ::DragQueryFile(hdrop, 0xffffffff, NULL, 0);
        for (int i = 0 ; i < filesDropped ; ++i)
        {
            char pathDropped[MAX_PATH];
            ::DragQueryFile(hdrop, i, pathDropped, sizeof(pathDropped));
            if (!doOpen(pathDropped))
            {
                break;
            }
            setLangStatus(_pEditView->getCurrentDocType());
        }
        ::DragFinish(hdrop);
        // Put Notepad_plus to forefront
        // May not work for Win2k, but OK for lower versions
        // Note: how to drop a file to an iconic window?
        // Actually, it is the Send To command that generates a drop.
        if (::IsIconic(_hSelf))
        {
            ::ShowWindow(_hSelf, SW_RESTORE);
        }
        ::SetForegroundWindow(_hSelf);
    }
}

void Notepad_plus::checkModifiedDocument()
{
    const int NB_VIEW = 2;
    ScintillaEditView * pScintillaArray[NB_VIEW];
    DocTabView * pDocTabArray[NB_VIEW];

    // the oder (1.current view 2.non current view) is important
    // to synchronize with "hideCurrentView" function
    pScintillaArray[0] = _pEditView;
    pScintillaArray[1] = getNonCurrentEditView();

    pDocTabArray[0] = _pDocTab;
    pDocTabArray[1] = getNonCurrentDocTab();

    for (int j = 0 ; j < NB_VIEW ; j++)
    {
        for (int i = (pScintillaArray[j]->getNbDoc()-1) ; i >= 0  ; i--)
        {
            Buffer & docBuf = pScintillaArray[j]->getBufferAt(i);
            docFileStaus fStatus = docBuf.checkFileState();
            pDocTabArray[j]->updateTabItem(i);

            if (fStatus == MODIFIED_FROM_OUTSIDE)
            {
                if (doReloadOrNot(docBuf.getFileName()) == IDYES)
                {
                    pDocTabArray[j]->activate(i);
                    reload(docBuf.getFileName());
                }
                docBuf.updatTimeStamp();
            }
            else if (fStatus == FILE_DELETED)
            {
                if (doCloseOrNot(docBuf.getFileName()) == IDNO)
                {
                    pDocTabArray[j]->activate(i);
                    //_pDocTab->closeCurrentDoc();
                    if ((pScintillaArray[j]->getNbDoc() == 1) && (_mainWindowStatus & TWO_VIEWS_MASK))
                    {
                        pDocTabArray[j]->closeCurrentDoc();
                        hideCurrentView();
                    }
                    else
                        pDocTabArray[j]->closeCurrentDoc();
                }
            }
            
            bool isReadOnly = pScintillaArray[j]->isCurrentBufReadOnly();
            pScintillaArray[j]->execute(SCI_SETREADONLY, isReadOnly);
            //_pDocTab->updateCurrentTabItem();
        }
    }
}

void Notepad_plus::hideCurrentView()
{
    if (_mainWindowStatus & DOCK_MASK)
    {
        _pMainSplitter->setWin0(getNonCurrentDocTab());
        //_pMainWindow = _pMainSplitter;
    }
    else // otherwise the main window is the spltter container that we just created
        _pMainWindow = getNonCurrentDocTab();
        
    _subSplitter.display(false);
    _pEditView->display(false);
    _pDocTab->display(false);

    // resize the main window
    RECT rc;
    getMainClientRect(rc);
    _pMainWindow->reSizeTo(rc);

    switchEditViewTo((getCurrentView() == MAIN_VIEW)?SUB_VIEW:MAIN_VIEW);

    //setTitleWith(_pEditView->getCurrentTitle());

    _mainWindowStatus &= ~TWO_VIEWS_MASK;
}

bool Notepad_plus::fileClose()
{
    int res;
    bool isDirty = _pEditView->isCurrentDocDirty();
    if (isDirty)
    {
        if ((res = doSaveOrNot(_pEditView->getCurrentTitle())) == IDYES)
        {
            if (!fileSave()) // the cancel button of savdialog is pressed
                return false;
        }
        else if (res == IDCANCEL)
            return false;
        // else IDNO we continue
    }

    //process the fileNamePath into LRF
    const char *fileNamePath = _pEditView->getCurrentTitle();

    //si ce n'est pas untited(avec prefixe "new "), on fait le traitement
    if (!Buffer::isUntitled(fileNamePath))
    {
        //(NppParameters::getInstance())->writeHistory(fileNamePath);
        _lastRecentFileList.set(fileNamePath);
    }

    
    if ((_pEditView->getNbDoc() == 1) && (_mainWindowStatus & TWO_VIEWS_MASK))
    {
        _pDocTab->closeCurrentDoc();
        hideCurrentView();
        return true;
    }

    setTitleWith(_pDocTab->closeCurrentDoc());
    return true;
}

bool Notepad_plus::fileCloseAll()
{
    if (_mainWindowStatus & TWO_VIEWS_MASK)
    {
        while (_pEditView->getNbDoc() > 1)
            if (!fileClose())
                return false;

        if (!fileClose())
            return false;
    }

    while (_pEditView->getNbDoc() > 1)
        if (!fileClose())
            return false;
    return fileClose();
}

bool Notepad_plus::fileCloseAllButCurrent()
{
    int curIndex = _pEditView->getCurrentDocIndex();
    _pEditView->activateDocAt(0);

    for (int i = 0 ; i < curIndex ; i++)
        if (!fileClose())
                return false;

    if (_pEditView->getNbDoc() > 1)
    {
        _pEditView->activateDocAt(1);
        while (_pEditView->getNbDoc() > 1)
            if (!fileClose())
                return false;
    }
    if (_mainWindowStatus & TWO_VIEWS_MASK)
    {
        switchEditViewTo(getNonCurrentView());
        while (_pEditView->getNbDoc() > 1)
            if (!fileClose())
                return false;
        return fileClose();
    }
    return true;
}

void Notepad_plus::reload(const char *fileName)
{
    FILE *fp = fopen(fileName, "rb");
    if (fp)
    {
        //setTitleWith(_pDocTab->newDoc(fileName));

        // It's VERY IMPORTANT to reset the view
        _pEditView->execute(SCI_CLEARALL);

        const int blockSize = 128 * 1024;
        char data[blockSize];

        int lenFile = int(fread(data, 1, sizeof(data), fp));
        while (lenFile > 0) {
            _pEditView->execute(SCI_ADDTEXT, lenFile, reinterpret_cast<LPARAM>(static_cast<char *>(data)));
            lenFile = int(fread(data, 1, sizeof(data), fp));
        }
        fclose(fp);

        _pEditView->getFocus();
        _pEditView->execute(SCI_SETSAVEPOINT);
        _pEditView->execute(EM_EMPTYUNDOBUFFER);
//        return true;
    }
    else
    {
        char msg[MAX_PATH + 100];
        strcpy(msg, "Could not open file \"");
        //strcat(msg, fullPath);
        strcat(msg, fileName);
        strcat(msg, "\".");
        ::MessageBox(_hSelf, msg, "ERR", MB_OK);
//        return false;
    }
}

void Notepad_plus::getMainClientRect(RECT &rc) const
{
    Window::getClientRect(rc);
    rc.top += _toolBar.getHeight() + 2;
    rc.bottom -= _toolBar.getHeight() + 2 +_statusBar.getHeight();
}

void Notepad_plus::getToolBarClientRect(RECT &rc) const
{
    Window::getClientRect(rc);
    rc.bottom = _toolBar.getHeight();
}

void Notepad_plus::getStatusBarClientRect(RECT & rc) const
{
    RECT rectMain;
    
    getMainClientRect(rectMain);
    getClientRect(rc);
    rc.top = rectMain.top + rectMain.bottom;
    rc.bottom = rc.bottom - rc.top;
}

void Notepad_plus::dockUserDlg()
{
    if (!_pMainSplitter)
    {
        _pMainSplitter = new SplitterContainer;
        _pMainSplitter->init(_hInst, _hSelf);

        Window *pWindow;
        if (_mainWindowStatus & TWO_VIEWS_MASK)
            pWindow = &_subSplitter;
        else
            pWindow = _pDocTab;

        _pMainSplitter->create(pWindow, ScintillaEditView::getUserDefineDlg(), 8, RIGHT_FIX, 45);
    }

    if (_mainWindowStatus & TWO_VIEWS_MASK)
        _pMainSplitter->setWin0(&_subSplitter);
    else
        _pMainSplitter->setWin0(_pDocTab);

    RECT rc;
    
    getMainClientRect(rc);
    _pMainSplitter->reSizeTo(rc);
    _pMainSplitter->display();

    _mainWindowStatus |= DOCK_MASK;
    _pMainWindow = _pMainSplitter;
}

void Notepad_plus::undockUserDlg()
{
    // a cause de surchargement de "display"
    ::ShowWindow(_pMainSplitter->getHSelf(), SW_HIDE);

    if (_mainWindowStatus & TWO_VIEWS_MASK)
        _pMainWindow = &_subSplitter;
    else
        _pMainWindow = _pDocTab;
    
    RECT rc;
    getMainClientRect(rc);
    _pMainWindow->reSizeTo(rc);

    _mainWindowStatus &= ~DOCK_MASK;
    (ScintillaEditView::getUserDefineDlg())->display();
    //(_pEditView->getUserDefineDlg())->display();
}

void Notepad_plus::docGotoAnotherEditView(bool mode)
{
    if (!(_mainWindowStatus & TWO_VIEWS_MASK))
    {
        // if there's dock dialog, it means there's also a splitter container
        // we replace the right window by sub-spltter container that we just created
        if (_mainWindowStatus & DOCK_MASK)
        {
            _pMainSplitter->setWin0(&_subSplitter);
            _pMainWindow = _pMainSplitter;
        }
        else // otherwise the main window is the spltter container that we just created
            _pMainWindow = &_subSplitter;
        
        // resize the main window
        RECT rc;
        getMainClientRect(rc);
        _pMainWindow->reSizeTo(rc);

        getNonCurrentEditView()->display();
        getNonCurrentDocTab()->display();

        _pMainWindow->display();

        // update the main window status
        _mainWindowStatus |= TWO_VIEWS_MASK;
    }

    // Bon, define the source view and the dest view
    // source view
    DocTabView *pSrcDocTab;
    ScintillaEditView *pSrcEditView;
    if (getCurrentView() == MAIN_VIEW)
    {
        // make dest view
        switchEditViewTo(SUB_VIEW);

        // make source view
        pSrcDocTab = &_mainDocTab;
        pSrcEditView = &_mainEditView;

    }
    else
    {
        // make dest view : _pDocTab & _pEditView
        switchEditViewTo(MAIN_VIEW);

        // make source view
        pSrcDocTab = &_subDocTab;
        pSrcEditView = &_subEditView;
    }

    // Maintenant, we begin to manipulate the source and the dest:
    // 1. Save the current position of the source view to transfer
    pSrcEditView->saveCurrentPos();

    // 2. Retrieve the current buffer from the source
    Buffer & buf = pSrcEditView->getCurrentBuffer();

    // 3. See if the file to transfer exist in the dest view
    //    if so, we don't transfer the file(buffer)
    //    but activate the opened document in the dest view then beat it
    int i;
    if ( (i = _pDocTab->find(buf.getFileName())) != -1)
    {
        setTitleWith(_pDocTab->activate(i));
        _pDocTab->getFocus();
        return;
    }

    // 4. Transfer the file (buffer) into the dest view
    bool isNewDoc2Close = false;

    if ((_pEditView->getNbDoc() == 1)
        && Buffer::isUntitled(_pEditView->getCurrentTitle())
        && (!_pEditView->isCurrentDocDirty()) && (_pEditView->getCurrentDocLen() == 0))
    {
        isNewDoc2Close = true;
    }

    setTitleWith(_pDocTab->newDoc(buf));
    _pDocTab->updateCurrentTabItem(NULL);
    
    if (isNewDoc2Close)
        _pDocTab->closeDocAt(0);

    // 5. If it's the clone mode, we keep the document to transfer
    //    in the source view (do nothing). If it's the transfer mode
    //    we remove the file (buffer) from the source view
    if (mode != MODE_CLONE)
    {
        // Make focus to the source view
        switchEditViewTo((getCurrentView() == MAIN_VIEW)?SUB_VIEW:MAIN_VIEW);

        if (_pEditView->getNbDoc() == 1)
        {
            // close the current doc in the dest view
            _pDocTab->closeCurrentDoc();
            hideCurrentView();
        }
        else
        {
            // Make focus to the source view
            //switchEditViewTo((getCurrentView() == MAIN_VIEW)?SUB_VIEW:MAIN_VIEW);

            // close the current doc in the dest view
            _pDocTab->closeCurrentDoc();

            // return to state where the focus is on dest view
            switchEditViewTo((getCurrentView() == MAIN_VIEW)?SUB_VIEW:MAIN_VIEW);
        }
    }
}

void Notepad_plus::bookmarkNext(bool forwardScan)
{
    int lineno = _pEditView->getCurrentLineNumber();
    int sci_marker = SCI_MARKERNEXT;
    int lineStart = lineno + 1;    //Scan starting from next line
    int lineRetry = 0;                //If not found, try from the beginning
    if (!forwardScan)
    {
        lineStart = lineno - 1;        //Scan starting from previous line
        lineRetry = _pEditView->execute(SCI_GETLINECOUNT, 0, 0L);    //If not found, try from the end
        sci_marker = SCI_MARKERPREVIOUS;
    }
    int nextLine = _pEditView->execute(sci_marker, lineStart, 1 << MARK_SYMBOLE);
    if (nextLine < 0)
        nextLine = _pEditView->execute(sci_marker, lineRetry, 1 << MARK_SYMBOLE);
    /*
    if (nextLine < 0 || nextLine == lineno)    // No bookmark (of the given type) or only one, and already on it
        WarnUser(warnNoOtherBookmark);
    else {
        GotoLineEnsureVisible(nextLine);
    }
    */
    _pEditView->execute(SCI_ENSUREVISIBLEENFORCEPOLICY, nextLine);
    _pEditView->execute(SCI_GOTOLINE, nextLine);
}

void Notepad_plus::dynamicCheckMenuAndTB() const
{
    // Visibility of 3 margins
    checkMenuItem(IDM_VIEW_LINENUMBER, _pEditView->hasMarginShowed(ScintillaEditView::_SC_MARGE_LINENUMBER));
    checkMenuItem(IDM_VIEW_SYMBOLMARGIN, _pEditView->hasMarginShowed(ScintillaEditView::_SC_MARGE_SYBOLE));
    checkMenuItem(IDM_VIEW_FOLDERMAGIN, _pEditView->hasMarginShowed(ScintillaEditView::_SC_MARGE_FOLDER));
    // Folder margin style
    //changeCheckedItemFromTo(getFolderMarginStyle(), );
    checkFolderMarginStyleMenu(getFolderMaginStyleIDFrom(_pEditView->getFolderStyle()));

    // Visibility of invisible characters
    bool b = _pEditView->isInvisibleCharsShown();
    checkMenuItem(IDM_VIEW_ALL_CHARACTERS, b);
    _toolBar.setCheck(IDM_VIEW_ALL_CHARACTERS, b);

    // Visibility of the indentation guide line
    b = _pEditView->isShownIndentGuide();
    checkMenuItem(IDM_VIEW_INDENT_GUIDE, b);
    _toolBar.setCheck(IDM_VIEW_INDENT_GUIDE, b);

    // Current Line Highlighting
    checkMenuItem(IDM_VIEW_CURLINE_HILITING, _pEditView->isCurrentLineHiLiting());

    // Wrap
    b = _pEditView->isWrap();
    checkMenuItem(IDM_VIEW_WRAP, b);
    _toolBar.setCheck(IDM_VIEW_WRAP, b);

    //Format conversion
    enableConvertMenuItems((_pEditView->getCurrentBuffer()).getFormat());
    
}


ToolBarButtonUnit toolBarIcons[] = {
    {IDM_FILE_NEW,        IDI_NEW_OFF_ICON,        IDI_NEW_ON_ICON,        IDI_NEW_OFF_ICON},
    {IDM_FILE_OPEN,        IDI_OPEN_OFF_ICON,        IDI_OPEN_ON_ICON,        IDI_NEW_OFF_ICON},
    {IDM_FILE_SAVE,        IDI_SAVE_OFF_ICON,        IDI_SAVE_ON_ICON,        IDI_SAVE_DISABLE_ICON},
    {IDM_FILE_SAVEALL,    IDI_SAVEALL_OFF_ICON,    IDI_SAVEALL_ON_ICON,    IDI_SAVEALL_DISABLE_ICON},
    {IDM_FILE_CLOSE,    IDI_CLOSE_OFF_ICON,        IDI_CLOSE_ON_ICON,        IDI_CLOSE_OFF_ICON},
    {IDM_FILE_CLOSEALL,    IDI_CLOSEALL_OFF_ICON,    IDI_CLOSEALL_ON_ICON,    IDI_CLOSEALL_OFF_ICON},
    
    //-------------------------------------------------------------------------------------//
    {0,                    IDI_SEPARATOR_ICON,        IDI_SEPARATOR_ICON,        IDI_SEPARATOR_ICON},
    //-------------------------------------------------------------------------------------//
    
    {IDM_EDIT_CUT,        IDI_CUT_OFF_ICON,        IDI_CUT_ON_ICON,        IDI_CUT_DISABLE_ICON},
    {IDM_EDIT_COPY,        IDI_COPY_OFF_ICON,        IDI_COPY_ON_ICON,        IDI_COPY_DISABLE_ICON},
    {IDM_EDIT_PASTE,    IDI_PASTE_OFF_ICON,        IDI_PASTE_ON_ICON,        IDI_PASTE_DISABLE_ICON},
    
    //-------------------------------------------------------------------------------------//
    {0,                    IDI_SEPARATOR_ICON,        IDI_SEPARATOR_ICON,        IDI_SEPARATOR_ICON},
    //-------------------------------------------------------------------------------------//
    
    {IDM_EDIT_UNDO,        IDI_UNDO_OFF_ICON,        IDI_UNDO_ON_ICON,        IDI_UNDO_DISABLE_ICON},
    {IDM_EDIT_REDO,        IDI_REDO_OFF_ICON,        IDI_REDO_ON_ICON,        IDI_REDO_DISABLE_ICON},
    
    //-------------------------------------------------------------------------------------//
    {0,                    IDI_SEPARATOR_ICON,        IDI_SEPARATOR_ICON,        IDI_SEPARATOR_ICON},
    //-------------------------------------------------------------------------------------//
    
    {IDM_SEARCH_FIND,        IDI_FIND_OFF_ICON,        IDI_FIND_ON_ICON,        IDI_FIND_OFF_ICON},
    {IDM_SEARCH_REPLACE,  IDI_REPLACE_OFF_ICON,    IDI_REPLACE_ON_ICON,    IDI_REPLACE_OFF_ICON},
    
    //-------------------------------------------------------------------------------------//
    {0,                    IDI_SEPARATOR_ICON,        IDI_SEPARATOR_ICON,        IDI_SEPARATOR_ICON},
    //-------------------------------------------------------------------------------------//

    {IDM_VIEW_ZOOMIN,    IDI_ZOOMIN_OFF_ICON,    IDI_ZOOMIN_ON_ICON,        IDI_ZOOMIN_OFF_ICON},
    {IDM_VIEW_ZOOMOUT,    IDI_ZOOMOUT_OFF_ICON,    IDI_ZOOMOUT_ON_ICON,    IDI_ZOOMOUT_OFF_ICON},

    //-------------------------------------------------------------------------------------//
    {0,                    IDI_SEPARATOR_ICON,        IDI_SEPARATOR_ICON,        IDI_SEPARATOR_ICON},
    //-------------------------------------------------------------------------------------//
{IDM_VIEW_WRAP,  IDI_VIEW_WRAP_OFF_ICON,    IDI_VIEW_WRAP_ON_ICON,    IDI_VIEW_WRAP_OFF_ICON},
{IDM_VIEW_ALL_CHARACTERS,  IDI_VIEW_ALL_CHAR_OFF_ICON,    IDI_VIEW_ALL_CHAR_ON_ICON,    IDI_VIEW_ALL_CHAR_OFF_ICON},
{IDM_VIEW_INDENT_GUIDE,  IDI_VIEW_INDENT_OFF_ICON,    IDI_VIEW_INDENT_ON_ICON,    IDI_VIEW_INDENT_OFF_ICON},
{IDM_VIEW_USER_DLG,  IDI_VIEW_UD_DLG_OFF_ICON,    IDI_VIEW_UD_DLG_ON_ICON,    IDI_VIEW_UD_DLG_OFF_ICON},

    //-------------------------------------------------------------------------------------//
    {0,                    IDI_SEPARATOR_ICON,        IDI_SEPARATOR_ICON,        IDI_SEPARATOR_ICON},
    //-------------------------------------------------------------------------------------//
    
    {IDC_BUTTON_PRINT,    IDI_PRINT_OFF_ICON,        IDI_PRINT_ON_ICON,        IDI_PRINT_OFF_ICON}
};    
                    
int docTabIconIDs[] = {IDI_SAVED_ICON, IDI_UNSAVED_ICON, IDI_READONLY_ICON};


LRESULT Notepad_plus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
    switch (Message)
    {
        case WM_CREATE:
        {
            const NppGUI & nppGUI = (NppParameters::getInstance())->getNppGUI();

            //-- Tool Bar Section --//
            toolBarStatusType tbStatus = nppGUI._toolBarStatus;

            // TB_LARGE par default
            int iconSize = 32;
            bool willBeShown = true;
            int menuID = IDM_VIEW_TOOLBAR_ENLARGE;

            if (tbStatus == TB_HIDE)
            {
                willBeShown = false;
                menuID = IDM_VIEW_TOOLBAR_HIDE;
            }
            else if (tbStatus == TB_SMALL)
            {
                iconSize = 16;
                menuID = IDM_VIEW_TOOLBAR_REDUCE;
            }
            _toolBar.init(_hInst, hwnd, iconSize, toolBarIcons, sizeof(toolBarIcons)/sizeof(ToolBarButtonUnit));
            _toolBar.display(willBeShown);
            checkToolBarMenu(menuID);

            _pDocTab = &_mainDocTab;
            _pEditView = &_mainEditView;

            const ScintillaViewParams & svp1 = (NppParameters::getInstance())->getSVP(SCIV_PRIMARY);
            const ScintillaViewParams & svp2 = (NppParameters::getInstance())->getSVP(SCIV_SECOND);

            _mainEditView.init(_hInst, hwnd);
            _subEditView.init(_hInst, hwnd);
            _mainEditView.display();


            // Configuration of 2 scintilla views
            _mainEditView.showMargin(ScintillaEditView::_SC_MARGE_LINENUMBER, svp1._lineNumberMarginShow);
            _subEditView.showMargin(ScintillaEditView::_SC_MARGE_LINENUMBER, svp2._lineNumberMarginShow);
            _mainEditView.showMargin(ScintillaEditView::_SC_MARGE_SYBOLE, svp1._bookMarkMarginShow);
            _subEditView.showMargin(ScintillaEditView::_SC_MARGE_SYBOLE, svp2._bookMarkMarginShow);

            _mainEditView.showIndentGuideLine(svp1._indentGuideLineShow);
            _subEditView.showIndentGuideLine(svp2._indentGuideLineShow);
            
            _configStyleDlg.init(_hInst, _hSelf);
            //Marker Margin config
            _mainEditView.setMakerStyle(svp1._folderStyle);
            _subEditView.setMakerStyle(svp2._folderStyle);

            _mainEditView.execute(SCI_SETCARETLINEVISIBLE, svp1._currentLineHilitingShow);
            _subEditView.execute(SCI_SETCARETLINEVISIBLE, svp2._currentLineHilitingShow);

            _mainEditView.performGlobalStyles();
            _subEditView.performGlobalStyles();


            _docTabIconList.create(20, _hInst, docTabIconIDs, sizeof(docTabIconIDs)/sizeof(int));

            const char * str = _mainDocTab.init(_hInst, hwnd, &_mainEditView, &_docTabIconList);
            setTitleWith(str);
            _subDocTab.init(_hInst, hwnd, &_subEditView, &_docTabIconList);
            TabBar::doDragNDrop(true);
            _mainDocTab.display();

            int tabBarStatus = nppGUI._tabStatus;
            TabBar::doDragNDrop((tabBarStatus & TAB_DRAGNDROP) != 0);
            TabBar::setDrawTopBar((tabBarStatus & TAB_DRAWTOPBAR) != 0);
            TabBar::setDrawInactiveTab((tabBarStatus & TAB_DRAWINACTIVETAB) != 0);

            checkMenuItem(IDM_VIEW_LOCKTABBAR, !TabBar::doDragNDropOrNot());
            checkMenuItem(IDM_VIEW_DRAWTABBAR_INACIVETAB, TabBar::drawInactiveTab());
            checkMenuItem(IDM_VIEW_DRAWTABBAR_TOPBAR, TabBar::drawTopBar());

            //--Splitter Section--//
            bool isVertical = (nppGUI._splitterPos == POS_VERTICAL);

            _subSplitter.init(_hInst, _hSelf);
            _subSplitter.create(&_mainDocTab, &_subDocTab, 8, DYNAMIC, 50, isVertical);

            //--Status Bar Section--//
            willBeShown = nppGUI._statusBarShow;
            _statusBar.init(_hInst, hwnd, 4);
            _statusBar.setPartWidth(1, 120);
            _statusBar.setPartWidth(2, 80);
            _statusBar.setPartWidth(3, 30);
            _statusBar.display(willBeShown);
            //
            checkMenuItem(IDM_VIEW_STATUSBAR, willBeShown);
            
            _findReplaceDlg.init(_hInst, hwnd, &_pEditView);
            _goToLineDlg.init(_hInst, hwnd, &_pEditView);
            _aboutDlg.init(_hInst, hwnd);
            _runDlg.init(_hInst, hwnd);
            
            checkMenuItem(IDM_SETTING_TAB_REPLCESPACE, nppGUI._tabReplacedBySpace);

            _pMainWindow = &_mainDocTab;

            //--Web Browser Section--//
            // WebControl bug
            //_webBrowser.init(_hInst, hwnd);

            //--User Define Dialog Section--//
            int uddStatus = nppGUI._userDefineDlgStatus;
            UserDefineDialog *udd = _pEditView->getUserDefineDlg();
            udd->create(IDD_USER_DEFINE_BOX);


            bool uddShow = false;
          switch (uddStatus)
            {
                case UDD_SHOW :                 // show & undocked
                    udd->display(true);
                    uddShow = true;
                    break;
                case UDD_DOCKED : {              // hide & docked
                    udd->changeStyle();
                    udd->display(false);
                    break;}
                case (UDD_SHOW | UDD_DOCKED) :    // show & docked
                    udd->doDialog();
                    ::SendMessage(udd->getHSelf(), WM_COMMAND, IDC_DOCK_BUTTON, 0);
                    uddShow = true;
                    break;

                default :                        // hide & undocked
                    udd->display(false);
            }
                    // UserDefine Dialog
            
            checkMenuItem(IDM_VIEW_USER_DLG, uddShow);
            _toolBar.setCheck(IDM_VIEW_USER_DLG, uddShow);

            dynamicCheckMenuAndTB();
            _mainEditView.defineDocType(L_TXT);
            HMENU hMenu = ::GetSubMenu(::GetMenu(_hSelf), 0);

            _nbLRFile = (NppParameters::getInstance())->getNbLRFile();
            int pos = 11;//GetMenuItemCount(hMenu) - 1 + 3/*separateurs*/;
            int k = 0;
            for (int i = 0, j = 0 ; i < _nbLRFile ; i++)
            {
                std::string * stdStr = (NppParameters::getInstance())->getLRFile(i);
                if (PathFileExists(stdStr->c_str()))
                {
                    _lastRecentFileList.add(stdStr->c_str());
                    ::InsertMenu(hMenu, pos + j , MF_BYPOSITION, IDM_FILE_EXIT + j + 1, stdStr->c_str());
                    j++;
                }
                else
                {
                    k++;
                }
            }
            if (_nbLRFile)
                ::InsertMenu(hMenu, pos + _nbLRFile - k, MF_BYPOSITION, -1, 0);

            //updateStatusBar();
            _hExplorer = ::LoadLibrary(EXPLORER_PLUGIN_PATH);
            if (_hExplorer)
            {
                _doExplorer = (HWND (__cdecl *)(HINSTANCE, HWND))::GetProcAddress(_hExplorer, "doExplorer");
                if (_doExplorer)
                {
                    HWND hBrowser = _doExplorer(_hInst, _hSelf);
                    ::ShowWindow(hBrowser, SW_SHOW);
                }
            }
            return TRUE;
        }
        
        case WM_DRAWITEM :
        {
            DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)lParam;
            if (dis->CtlType == ODT_TAB)
            {
                return ::SendMessage(dis->hwndItem, WM_DRAWITEM, wParam, lParam);
            }
        }

        case WM_DOCK_USERDEFINE_DLG:
        {
            dockUserDlg();
            return TRUE;
        }

        case WM_UNDOCK_USERDEFINE_DLG:
        {
            undockUserDlg();
            return TRUE;
        }

        case WM_CLOSE_USERDEFINE_DLG :
        {
            checkMenuItem(IDM_VIEW_USER_DLG, false);
            _toolBar.setCheck(IDM_VIEW_USER_DLG, false);
            return TRUE;
        }

        case WM_SIZE:
        {
            RECT rc;
            getToolBarClientRect(rc);
            _toolBar.reSizeTo(rc);

            getMainClientRect(rc);
            _pMainWindow->reSizeTo(rc);

            getStatusBarClientRect(rc);
            _statusBar.reSizeTo(rc);
            return TRUE;
        }

        case WM_MOVE:
        {
            redraw();
            return TRUE;
        }

        case WM_COPYDATA :
        {
            COPYDATASTRUCT *pCopyData = (COPYDATASTRUCT *)lParam;
            FileNameStringSplitter fnss((const char *)pCopyData->lpData);
            char *pFn = NULL;
            for (int i = 0 ; i < fnss.size() ; i++)
            {
                pFn = (char *)fnss.getFileName(i);
                doOpen((const char *)pFn);
            }
            return TRUE;
        }

        case WM_COMMAND:
            if (HIWORD(wParam) == SCEN_SETFOCUS)
            {
                switchEditViewTo((lParam == (LPARAM)_mainEditView.getHSelf())?MAIN_VIEW:SUB_VIEW);
            }
            else
                command(LOWORD(wParam));

            return TRUE;

        case WM_NOTIFY:
        {
            checkClipboard();
            checkUndoState();
            notify(reinterpret_cast<SCNotification *>(lParam));
            return FALSE;
        }

        case WM_ACTIVATEAPP :
        {
            if (LOWORD(wParam))
            {
                checkModifiedDocument();
                return FALSE;
            }
            return ::DefWindowProc(hwnd, Message, wParam, lParam);
        }


        case WM_ACTIVATE :
            _pEditView->getFocus();
            return TRUE;

        case WM_DROPFILES:
        {
            dropFiles(reinterpret_cast<HDROP>(wParam));
            return TRUE;
        }

        case WM_UPDATESCINTILLAS:
        {
            _mainEditView.defineDocType(_mainEditView.getCurrentDocType());
            _subEditView.defineDocType(_subEditView.getCurrentDocType());
            _mainEditView.performGlobalStyles();
            _subEditView.performGlobalStyles();
            return TRUE;
        }

        case WM_CLOSE:
        {
            if (fileCloseAll())
            {
                _lastRecentFileList.saveLRFL();
                saveScintillaParams(SCIV_PRIMARY);
                saveScintillaParams(SCIV_SECOND);
                saveGUIParams();
                ::DestroyWindow(hwnd);
            }
            return TRUE;
        }

        case WM_DESTROY:
        {    
            killAllChildren();    
            if (_hExplorer)
            {
                ::FreeLibrary(_hExplorer);
            }
        
            ::PostQuitMessage(0);
            return TRUE;
        }
/*
        case WM_QUIT :
        {
            
            return TRUE;
        }
*/
        default:
        {
            return ::DefWindowProc(hwnd, Message, wParam, lParam);
        }
    }
    return FALSE;
}

LRESULT CALLBACK Notepad_plus::Notepad_plus_Proc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
  switch(Message)
  {
    case WM_NCCREATE : // First message we get the ptr of instantiated object
                       // then stock it into GWL_USERDATA index in order to retrieve afterward
    {
        Notepad_plus *pM30ide = (Notepad_plus *)(((LPCREATESTRUCT)lParam)->lpCreateParams);
        pM30ide->_hSelf = hwnd;
        ::SetWindowLong(hwnd, GWL_USERDATA, (LONG)pM30ide);

        return TRUE;
    }

    default :
    {
      return ((Notepad_plus *)::GetWindowLong(hwnd, GWL_USERDATA))->runProc(hwnd, Message, wParam, lParam);
    }
  }
}