/******************************************************************** * Module: editor.cpp. This is part of Visual-MinGW. * * Purpose: Procedures to manage Scintilla editor. * * Authors: These classes are based on SciTE release 1.39. * http://www.scintilla.org/ * SciTE original code by Neil Hodgson. * Present revised code by Manu B. * * License: Both SciTE and Scintilla are covered by * "License for Scintilla and SciTE" agreement terms detailed in license.htm. * Present revised code is covered by GNU General Public License. * * Revisions: * ********************************************************************/ #include #include #include "commctrl.h" #include "commdlg.h" #include "editor.h" #include "rsrc.h" extern CMessageBox MsgBox; int Minimum(int a, int b); int Maximum(int a, int b); int Minimum(int a, int b){ if (a < b) return a; else return b; } int Maximum(int a, int b){ if (a > b) return a; else return b; } void EnsureRangeVisible(HWND hwndCtrl, int posStart, int posEnd, bool enforcePolicy){ int lineStart = SendMessage(hwndCtrl, SCI_LINEFROMPOSITION, Minimum(posStart, posEnd), 0); int lineEnd = SendMessage(hwndCtrl, SCI_LINEFROMPOSITION, Maximum(posStart, posEnd), 0); for (int line = lineStart; line <= lineEnd; line++){ SendMessage(hwndCtrl, enforcePolicy ? SCI_ENSUREVISIBLEENFORCEPOLICY : SCI_ENSUREVISIBLE, line, 0); } } int LengthDocument(HWND hwndCtrl){ return SendMessage(hwndCtrl, SCI_GETLENGTH, 0, 0); } CharacterRange GetSelection(HWND hwndCtrl){ CharacterRange crange; crange.cpMin = SendMessage(hwndCtrl, SCI_GETSELECTIONSTART, 0, 0); crange.cpMax = SendMessage(hwndCtrl, SCI_GETSELECTIONEND, 0, 0); return crange; } /******************************************************************** * Class: CChooseFontDlg. * * Purpose: * * Revisions: * ********************************************************************/ CChooseFontDlg::CChooseFontDlg(){ ZeroMemory(&lf, sizeof(LOGFONT)); /* lf.lfHeight; lf.lfWidth; lf.lfEscapement; lf.lfOrientation; lf.lfWeight; lf.lfItalic; lf.lfUnderline; lf.lfStrikeOut; lf.lfCharSet; lf.lfOutPrecision; lf.lfClipPrecision; lf.lfQuality; lf.lfPitchAndFamily; lf.lfFaceName[LF_FACESIZE];*/ cf.lStructSize = sizeof(CHOOSEFONT); cf.hwndOwner = 0; cf.hDC = NULL; cf.lpLogFont = &lf;//&(Profile.LogFont); cf.iPointSize = 0; cf.Flags = /*CF_INITTOLOGFONTSTRUCT |*/ CF_SCREENFONTS | CF_EFFECTS /*| CF_ENABLEHOOK*/; cf.rgbColors = 0;//Profile.rgbForeColor; cf.lCustData = 0; cf.lpfnHook = NULL; cf.lpTemplateName = NULL; cf.hInstance = NULL; cf.lpszStyle = NULL; cf.nFontType = SCREEN_FONTTYPE; cf.nSizeMin = 0; cf.nSizeMax = 0; } CChooseFontDlg::~CChooseFontDlg(){ } bool CChooseFontDlg::Create(CWindow * pWindow){ cf.hwndOwner = pWindow->_hWnd; return ChooseFont(&cf); } /*bool ChooseNewFont(HWND hWndListBox){ static CHOOSEFONT cf; static BOOL bFirstTime = TRUE; HFONT hFont; if(bFirstTime){ bFirstTime = false; } if(ChooseFont(&cf)){ HDC hDC; hFont = CreateFontIndirect( &(Profile.LogFont) ); hDC = GetDC( hWndListBox ); SelectObject( hDC, hFont ); Profile.rgbForeColor = cf.rgbColors; InvalidateRect( hWndListBox, NULL, TRUE ); SendMessage( hWndListBox, WM_CTLCOLORLISTBOX, (DWORD) hDC, (LONG) hWndListBox ); SendMessage( hWndListBox, WM_SETFONT, (DWORD) hFont, TRUE ); ReleaseDC( hWndListBox, hDC ); } return true; }*/ /******************************************************************** * Class: CFindReplaceDlg. * * Purpose: * * Revisions: * ********************************************************************/ CFindReplaceDlg::CFindReplaceDlg(){ pEditor = NULL; hEditor = 0; resId = 0; *findWhat = '\0'; *replaceWhat = '\0'; bWholeWord = false; bMatchCase = true; bRegExp = false; bWrapFind = false; bUnSlash = false; bReverseFind = false; bHavefound = false; } CFindReplaceDlg::~CFindReplaceDlg(){ } HWND CFindReplaceDlg::Find(CScintilla * pEditor){ if (_hWnd || !pEditor) return 0; return CreateParam(pEditor, IDD_FIND, (long) IDD_FIND); } HWND CFindReplaceDlg::Replace(CScintilla * pEditor){ if (_hWnd || !pEditor) return 0; return CreateParam(pEditor, IDD_REPLACE, (long) IDD_REPLACE); } LRESULT CALLBACK CFindReplaceDlg::CDlgProc(UINT Message, WPARAM wParam, LPARAM lParam){ switch(Message){ case WM_INITDIALOG: return OnInitDialog((HWND) wParam, lParam); case WM_COMMAND: OnCommand(HIWORD(wParam), LOWORD(wParam), (HWND) lParam); break; case WM_CLOSE: EndDlg(0); break; } return FALSE; } BOOL CFindReplaceDlg::OnInitDialog(HWND, LPARAM lInitParam){ // Set pointers. pEditor = (CEditor *) _pParent; if (pEditor == NULL) return TRUE; hEditor = pEditor->_hWnd; resId = lInitParam; hFindWhat = GetItem(IDC_FINDWHAT); hWholeWord = GetItem(IDC_WHOLEWORD); hMatchCase = GetItem(IDC_MATCHCASE); hRegExp = GetItem(IDC_REGEXP); hWrap = GetItem(IDC_WRAP); hUnSlash = GetItem(IDC_UNSLASH); if (resId == IDD_FIND) return Find_OnInitDialog(); else if (resId == IDD_REPLACE) return Replace_OnInitDialog(); return FALSE; } BOOL CFindReplaceDlg::Find_OnInitDialog(void){ hUp = GetItem(IDC_DIRECTIONUP); hDown = GetItem(IDC_DIRECTIONDOWN); SetItemText(hFindWhat, findWhat); //FillComboFromMemory(wFindWhat, memFinds); if (bWholeWord) ::SendMessage(hWholeWord, BM_SETCHECK, BST_CHECKED, 0); if (bMatchCase) ::SendMessage(hMatchCase, BM_SETCHECK, BST_CHECKED, 0); if (bRegExp) ::SendMessage(hRegExp, BM_SETCHECK, BST_CHECKED, 0); if (bWrapFind) ::SendMessage(hWrap, BM_SETCHECK, BST_CHECKED, 0); if (bUnSlash) ::SendMessage(hUnSlash, BM_SETCHECK, BST_CHECKED, 0); if (bReverseFind) { ::SendMessage(hUp, BM_SETCHECK, BST_CHECKED, 0); } else { ::SendMessage(hDown, BM_SETCHECK, BST_CHECKED, 0); } return TRUE; } BOOL CFindReplaceDlg::Replace_OnInitDialog(void){ SetItemText(hFindWhat, findWhat); //FillComboFromMemory(wFindWhat, sci->memFinds); hReplaceWith = GetItem(IDC_REPLACEWITH); SetItemText(hReplaceWith, replaceWhat); //FillComboFromMemory(wReplaceWith, sci->memReplaces); if (bWholeWord) ::SendMessage(hWholeWord, BM_SETCHECK, BST_CHECKED, 0); if (bMatchCase) ::SendMessage(hMatchCase, BM_SETCHECK, BST_CHECKED, 0); if (bRegExp) ::SendMessage(hRegExp, BM_SETCHECK, BST_CHECKED, 0); if (bWrapFind) ::SendMessage(hWrap, BM_SETCHECK, BST_CHECKED, 0); if (bUnSlash) ::SendMessage(hUnSlash, BM_SETCHECK, BST_CHECKED, 0); if ((findWhat) != '\0'){ ::SetFocus(hReplaceWith); return FALSE; } return TRUE; } BOOL CFindReplaceDlg::OnCommand(WORD, WORD wID, HWND){ if (resId == IDD_FIND) return Find_OnCommand(wID); else if (resId == IDD_REPLACE) return Replace_OnCommand(wID); return FALSE; } BOOL CFindReplaceDlg::Find_OnCommand(WORD wID){ switch (wID){ case IDOK: char s[200]; GetItemText(hFindWhat, s, sizeof(s)); strcpy(findWhat, s); //memFinds.Insert(s); bWholeWord = BST_CHECKED == ::SendMessage(hWholeWord, BM_GETCHECK, 0, 0); bMatchCase = BST_CHECKED == ::SendMessage(hMatchCase, BM_GETCHECK, 0, 0); bRegExp = BST_CHECKED == ::SendMessage(hRegExp, BM_GETCHECK, 0, 0); bWrapFind = BST_CHECKED == ::SendMessage(hWrap, BM_GETCHECK, 0, 0); bUnSlash = BST_CHECKED == ::SendMessage(hUnSlash, BM_GETCHECK, 0, 0); bReverseFind = BST_CHECKED == ::SendMessage(hUp, BM_GETCHECK, 0, 0); FindNext(bReverseFind, true); return TRUE; case IDCANCEL: EndDlg(IDCANCEL); return FALSE; } return FALSE; } BOOL CFindReplaceDlg::Replace_OnCommand(WORD wID){ if (wID == IDCANCEL){ EndDlg(IDCANCEL); return FALSE; }else{ return HandleReplaceCommand(wID); } return FALSE; } void CFindReplaceDlg::FindNext(bool reverseDirection, bool showWarnings){ if (!hEditor){ MsgBox.DisplayWarning("Can't get editor handle"); return; } if (!findWhat[0]) { // nothing to found //Find(hEditor); return; } char findTarget[FR_MAX_LEN + 1]; strcpy(findTarget, findWhat); // for C conversions -> int lenFind = UnSlashAsNeeded(findTarget, unSlash, regExp); int lenFind = strlen(findTarget); // normal return of UnSlashAsNeeded if (lenFind == 0) return; CharacterRange cr = GetSelection(hEditor); int startPosition = cr.cpMax; int endPosition = LengthDocument(hEditor); if (reverseDirection){ startPosition = cr.cpMin - 1; endPosition = 0; } int flags = (bWholeWord ? SCFIND_WHOLEWORD : 0) | (bMatchCase ? SCFIND_MATCHCASE : 0) | (bRegExp ? SCFIND_REGEXP : 0); ::SendMessage(hEditor, SCI_SETTARGETSTART, startPosition, 0); ::SendMessage(hEditor, SCI_SETTARGETEND, endPosition, 0); ::SendMessage(hEditor, SCI_SETSEARCHFLAGS, flags, 0); int posFind = ::SendMessage(hEditor, SCI_SEARCHINTARGET, lenFind, (LPARAM) findTarget); if (posFind == -1 && bWrapFind){ // not found with wrapFind // Failed to find in indicated direction // so search from the beginning (forward) or from the end (reverse) // unless wrapFind is false if (reverseDirection){ startPosition = LengthDocument(hEditor); endPosition = 0; } else { startPosition = 0; endPosition = LengthDocument(hEditor); } ::SendMessage(hEditor, SCI_SETTARGETSTART, startPosition, 0); ::SendMessage(hEditor, SCI_SETTARGETEND, endPosition, 0); posFind = ::SendMessage(hEditor, SCI_SEARCHINTARGET, lenFind, (LPARAM) findTarget); } if (posFind == -1){ // not found bHavefound = false; if (showWarnings){ /*warn that not found WarnUser(warnNotFound);*/ if (strlen(findWhat) > FR_MAX_LEN) findWhat[FR_MAX_LEN] = '\0'; char msg[FR_MAX_LEN + 50]; strcpy(msg, "Cannot find the string \""); strcat(msg, findWhat); strcat(msg, "\"."); if (_hWnd){ MsgBox.DisplayWarning(msg); }else{ MessageBox(0, msg, "Message", MB_OK); } } }else{ // found bHavefound = true; int start = ::SendMessage(hEditor, SCI_GETTARGETSTART, 0, 0); int end = ::SendMessage(hEditor, SCI_GETTARGETEND, 0, 0); EnsureRangeVisible(hEditor, start, end, true); ::SendMessage(hEditor, SCI_SETSEL, start, end); } } BOOL CFindReplaceDlg::HandleReplaceCommand(int cmd){ if (!hEditor){ MsgBox.DisplayWarning("Can't get editor handle"); return false; } if ((cmd == IDOK) || (cmd == IDC_REPLACE) || (cmd == IDC_REPLACEALL) || (cmd == IDC_REPLACEINSEL)) { GetItemText(hFindWhat, findWhat, sizeof(findWhat)); //props.Set("find.what", findWhat); //memFinds.Insert(findWhat); bWholeWord = BST_CHECKED == ::SendMessage(hWholeWord, BM_GETCHECK, 0, 0); bMatchCase = BST_CHECKED == ::SendMessage(hMatchCase, BM_GETCHECK, 0, 0); bRegExp = BST_CHECKED == ::SendMessage(hRegExp, BM_GETCHECK, 0, 0); bWrapFind = BST_CHECKED == ::SendMessage(hWrap, BM_GETCHECK, 0, 0); bUnSlash = BST_CHECKED == ::SendMessage(hUnSlash, BM_GETCHECK, 0, 0); } if ((cmd == IDC_REPLACE) || (cmd == IDC_REPLACEALL) || (cmd == IDC_REPLACEINSEL)) { GetItemText(hReplaceWith, replaceWhat, sizeof(replaceWhat)); //memReplaces.Insert(replaceWhat); } if (cmd == IDOK) { FindNext(bReverseFind, true); // Find next } else if (cmd == IDC_REPLACE) { if (bHavefound){ ReplaceOnce(); } else { CharacterRange crange = GetSelection(hEditor); ::SendMessage(hEditor, SCI_SETSEL, crange.cpMin, crange.cpMin); FindNext(bReverseFind, true); if (bHavefound){ ReplaceOnce(); } } } else if ((cmd == IDC_REPLACEALL) || (cmd == IDC_REPLACEINSEL)){ ReplaceAll(cmd == IDC_REPLACEINSEL); } return TRUE; } void CFindReplaceDlg::ReplaceOnce(void){ if (bHavefound){ char replaceTarget[FR_MAX_LEN + 1]; strcpy(replaceTarget, replaceWhat); // for C conversions -> int replaceLen = UnSlashAsNeeded(replaceTarget, unSlash, regExp); int replaceLen = strlen(replaceTarget); // normal return of UnSlashAsNeeded CharacterRange cr = GetSelection(hEditor); ::SendMessage(hEditor, SCI_SETTARGETSTART, cr.cpMin, 0); ::SendMessage(hEditor, SCI_SETTARGETEND, cr.cpMax, 0); int lenReplaced = replaceLen; if (bRegExp) lenReplaced = ::SendMessage(hEditor, SCI_REPLACETARGETRE, replaceLen, (LPARAM) replaceTarget); else // Allow \0 in replacement ::SendMessage(hEditor, SCI_REPLACETARGET, replaceLen, (LPARAM) replaceTarget); ::SendMessage(hEditor, SCI_SETSEL, cr.cpMin + lenReplaced, cr.cpMin); bHavefound = false; } FindNext(bReverseFind, true); } void CFindReplaceDlg::ReplaceAll(bool inSelection){ char findTarget[FR_MAX_LEN + 1]; strcpy(findTarget, findWhat); // for C conversions -> int findLen = UnSlashAsNeeded(findTarget, unSlash, regExp); int findLen = strlen(findTarget); // normal return of UnSlashAsNeeded if (findLen == 0) { MessageBox(_hWnd, "Find string for \"Replace All\" must not be empty.", "Message", MB_OK | MB_ICONWARNING); return; } CharacterRange cr = GetSelection(hEditor); int startPosition = cr.cpMin; int endPosition = cr.cpMax; if (inSelection) { if (startPosition == endPosition) { MessageBox(_hWnd, "Selection for \"Replace in Selection\" must not be empty.", "Message", MB_OK | MB_ICONWARNING); return; } } else { endPosition = LengthDocument(hEditor); if (bWrapFind) { // Whole document startPosition = 0; } // If not wrapFind, replace all only from caret to end of document } char replaceTarget[FR_MAX_LEN + 1]; strcpy(replaceTarget, replaceWhat); // for C conversions -> int replaceLen = UnSlashAsNeeded(replaceTarget, unSlash, regExp); int replaceLen = strlen(replaceTarget); // normal return of UnSlashAsNeeded int flags = (bWholeWord ? SCFIND_WHOLEWORD : 0) | (bMatchCase ? SCFIND_MATCHCASE : 0) | (bRegExp ? SCFIND_REGEXP : 0); ::SendMessage(hEditor, SCI_SETTARGETSTART, startPosition, 0); ::SendMessage(hEditor, SCI_SETTARGETEND, endPosition, 0); ::SendMessage(hEditor, SCI_SETSEARCHFLAGS, flags, 0); int posFind = ::SendMessage(hEditor, SCI_SEARCHINTARGET, findLen, (LPARAM) findTarget); if ((findLen == 1) && bRegExp && (findTarget[0] == '^')) { // Special case for replace all start of line so it hits the first line posFind = startPosition; ::SendMessage(hEditor, SCI_SETTARGETSTART, startPosition, 0); ::SendMessage(hEditor, SCI_SETTARGETEND, startPosition, 0); } if ((posFind != -1) && (posFind <= endPosition)) { int lastMatch = posFind; ::SendMessage(hEditor, SCI_BEGINUNDOACTION, 0, 0); while (posFind != -1) { int lenTarget = ::SendMessage(hEditor, SCI_GETTARGETEND, 0, 0) - ::SendMessage(hEditor, SCI_GETTARGETSTART, 0, 0); int lenReplaced = replaceLen; if (bRegExp) lenReplaced = ::SendMessage(hEditor, SCI_REPLACETARGETRE, replaceLen, (LPARAM) replaceTarget); else ::SendMessage(hEditor, SCI_REPLACETARGET, replaceLen, (LPARAM) replaceTarget); // Modify for change caused by replacement endPosition += lenReplaced - lenTarget; lastMatch = posFind + lenReplaced; // For the special cases of start of line and end of line // Something better could be done but there are too many special cases if (lenTarget <= 0) lastMatch++; ::SendMessage(hEditor, SCI_SETTARGETSTART, lastMatch, 0); ::SendMessage(hEditor, SCI_SETTARGETEND, endPosition, 0); posFind = ::SendMessage(hEditor, SCI_SEARCHINTARGET, findLen, (LPARAM) findTarget); } if (inSelection) ::SendMessage(hEditor, SCI_SETSEL, startPosition, endPosition); else ::SendMessage(hEditor, SCI_SETSEL, lastMatch, lastMatch); ::SendMessage(hEditor, SCI_ENDUNDOACTION, 0, 0); } else { if (strlen(findWhat) > FR_MAX_LEN) findWhat[FR_MAX_LEN] = '\0'; char msg[FR_MAX_LEN + 50]; strcpy(msg, "No replacements because string \""); strcat(msg, findWhat); strcat(msg, "\" was not present."); MessageBox(_hWnd, msg, "Message", MB_OK | MB_ICONWARNING); } } /******************************************************************** * Class: CEditor. * * Purpose: * * Revisions: * ********************************************************************/ CEditor::CEditor(){ caretPos = 1; } CEditor::~CEditor(){ } void CEditor::LoadFile(CFileItem * file){ if (!file || !_hWnd) return; if (file->nFileOffset == 0) return; // Untitled file. SetLexer(file->type); ::SendMessage(_hWnd, SCI_CANCEL, 0, 0); ::SendMessage(_hWnd, SCI_SETUNDOCOLLECTION, 0, 0); FILE *fp = fopen(file->szFileName, "rb"); if (fp){ char data[blockSize]; int lenFile = fread(data, 1, sizeof(data), fp); while (lenFile > 0){ ::SendMessage(_hWnd, SCI_ADDTEXT, lenFile, (LPARAM) data); lenFile = fread(data, 1, sizeof(data), fp); } fclose(fp); }else{ MsgBox.DisplayWarning("Can't load file %s", file->szFileName); } ::SendMessage(_hWnd, SCI_SETUNDOCOLLECTION, 1, 0); ::SendMessage(_hWnd, EM_EMPTYUNDOBUFFER, 0, 0); ::SendMessage(_hWnd, SCI_SETSAVEPOINT, 0 , 0); ::SendMessage(_hWnd, SCI_GOTOPOS, 0, 0); } void GetFileType(CFileItem * file){ if (!file) return; if (file->nFileExtension){ char * ext = file->szFileName + file->nFileExtension; // H_FILE ? if (!stricmp(ext, "h")){ file->type = H_FILE; return; }else if (!stricmp(ext, "hpp")){ file->type = H_FILE; return; }else if (!stricmp(ext, "hxx")){ file->type = H_FILE; return; // C_FILE ? }else if (!stricmp(ext, "c")){ file->type = C_FILE; return; }else if (!stricmp(ext, "cpp")){ file->type = C_FILE; return; }else if (!stricmp(ext, "cxx")){ file->type = C_FILE; return; // RC_FILE ? }else if (!stricmp(ext, "rc")){ file->type = RC_FILE; return; } } file->type = U_FILE; return; } void CEditor::SaveFile(char * fullPath){ if (!_hWnd) return; FILE *fp = fopen(fullPath, "wb"); if (fp){ char data[blockSize + 1]; int lengthDoc = ::SendMessage(_hWnd, SCI_GETLENGTH, 0, 0); for (int i = 0; i < lengthDoc; i += blockSize) { int grabSize = lengthDoc - i; if (grabSize > blockSize) grabSize = blockSize; GetRange(i, i + grabSize, data); fwrite(data, grabSize, 1, fp); } fclose(fp); ::SendMessage(_hWnd, SCI_SETSAVEPOINT, 0, 0); }else{ MsgBox.DisplayWarning("Can't save file %s", fullPath); } } int CEditor::GetCurrentPos(void){ int currentPos = ::SendMessage(_hWnd, SCI_GETCURRENTPOS, 0,0); caretPos = ::SendMessage(_hWnd, SCI_LINEFROMPOSITION, currentPos, 0) + 1; return caretPos; } void CEditor::GetRange(int start, int end, char *text){ TextRange tr; tr.chrg.cpMin = start; tr.chrg.cpMax = end; tr.lpstrText = text; ::SendMessage(_hWnd, SCI_GETTEXTRANGE, 0, (LPARAM) &tr); } void CEditor::SetAStyle(int style, COLORREF fore, COLORREF back, int size, const char *face){ ::SendMessage(_hWnd, SCI_STYLESETFORE, style, fore); ::SendMessage(_hWnd, SCI_STYLESETBACK, style, back); if (size >= 1) ::SendMessage(_hWnd, SCI_STYLESETSIZE, style, size); if (face) ::SendMessage(_hWnd, SCI_STYLESETFONT, style, (LPARAM) face); } void CEditor::DefineMarker(int marker, int markerType, COLORREF fore, COLORREF back) { ::SendMessage(_hWnd, SCI_MARKERDEFINE, marker, markerType); ::SendMessage(_hWnd, SCI_MARKERSETFORE, marker, fore); ::SendMessage(_hWnd, SCI_MARKERSETBACK, marker, back); } void CEditor::SetLexer(int fileType){ switch (fileType){ case H_FILE: case C_FILE: case RC_FILE: SetCppLexer(); return; default: // Global default style. SetAStyle(STYLE_DEFAULT, black, white, 10, "Verdana"); ::SendMessage(_hWnd, SCI_STYLECLEARALL, 0, 0); // Copies to all other styles. } } void CEditor::SetCppLexer(void){ ::SendMessage(_hWnd, SCI_SETLEXER, SCLEX_CPP, 0); ::SendMessage(_hWnd, SCI_SETSTYLEBITS, 5, 0); ::SendMessage(_hWnd, SCI_SETKEYWORDS, 0, (LPARAM) cppKeyWords); // Global default style. SetAStyle(STYLE_DEFAULT, black, white, 10, "Verdana"); ::SendMessage(_hWnd, SCI_STYLECLEARALL, 0, 0); // Copies to all other styles. // C Styles. SetAStyle(SCE_C_DEFAULT, black, white, 10, "Verdana"); //0 SetAStyle(SCE_C_COMMENT, Green, white, 0, 0); //1 SetAStyle(SCE_C_COMMENTLINE, Green, white, 0, 0); //2 SetAStyle(SCE_C_COMMENTDOC, darkGreen, white, 0, 0); //3 SetAStyle(SCE_C_NUMBER, Ice, white, 0, 0); //4 SetAStyle(SCE_C_WORD, darkBlue, white, 0, 0); //5 ::SendMessage(_hWnd, SCI_STYLESETBOLD, SCE_C_WORD, 1); SetAStyle(SCE_C_STRING, Purple, white, 0, 0); //6 SetAStyle(SCE_C_CHARACTER, Purple, white, 0, 0); //7 SetAStyle(SCE_C_PREPROCESSOR, Olive, white, 0, 0); //9 SetAStyle(SCE_C_OPERATOR, black, white, 0, 0); //10 ::SendMessage(_hWnd, SCI_STYLESETBOLD, SCE_C_OPERATOR, 1); // SetAStyle(SCE_C_STRINGEOL, darkBlue, white, 0, 0); //12 // SetAStyle(SCE_C_COMMENTLINEDOC, darkBlue, white, 0, 0); //15 // SetAStyle(SCE_C_WORD2, darkBlue, white, 0, 0); //16 ::SendMessage(_hWnd, SCI_SETPROPERTY, (long)"fold", (long)"1"); ::SendMessage(_hWnd, SCI_SETPROPERTY, (long)"fold.compact", (long)"1"); ::SendMessage(_hWnd, SCI_SETPROPERTY, (long)"fold.symbols", (long)"1"); ::SendMessage(_hWnd, SCI_SETFOLDFLAGS, 16, 0); // To put the folder markers in the line number region //SendEditor(SCI_SETMARGINMASKN, 0, SC_MASK_FOLDERS); ::SendMessage(_hWnd, SCI_SETMODEVENTMASK, SC_MOD_CHANGEFOLD, 0); // Create a margin column for the folding symbols ::SendMessage(_hWnd, SCI_SETMARGINTYPEN, 2, SC_MARGIN_SYMBOL); ::SendMessage(_hWnd, SCI_SETMARGINWIDTHN, 2, /*foldMargin ? foldMarginWidth :*/ 16); ::SendMessage(_hWnd, SCI_SETMARGINMASKN, 2, SC_MASK_FOLDERS); ::SendMessage(_hWnd, SCI_SETMARGINSENSITIVEN, 2, 1); DefineMarker(SC_MARKNUM_FOLDEROPEN, SC_MARK_MINUS, white, black); DefineMarker(SC_MARKNUM_FOLDER, SC_MARK_PLUS, white, black); DefineMarker(SC_MARKNUM_FOLDERSUB, SC_MARK_EMPTY, white, black); DefineMarker(SC_MARKNUM_FOLDERTAIL, SC_MARK_EMPTY, white, black); DefineMarker(SC_MARKNUM_FOLDEREND, SC_MARK_EMPTY, white, black); DefineMarker(SC_MARKNUM_FOLDEROPENMID, SC_MARK_EMPTY, white, black); DefineMarker(SC_MARKNUM_FOLDERMIDTAIL, SC_MARK_EMPTY, white, black); return; } void CEditor::GotoLine(int line, char * /*fileName*/){ ::SendMessage(_hWnd, SCI_ENSUREVISIBLEENFORCEPOLICY, line, 0); ::SendMessage(_hWnd, SCI_GOTOLINE, line, 0); } bool CEditor::MarginClick(int position, int modifiers){ int lineClick = ::SendMessage(_hWnd, SCI_LINEFROMPOSITION, position, 0); //Platform::DebugPrintf("Margin click %d %d %x\n", position, lineClick, // ::SendMessage(_hWnd, SCI_GETFOLDLEVEL, lineClick) & SC_FOLDLEVELHEADERFLAG); /* if ((modifiers & SCMOD_SHIFT) && (modifiers & SCMOD_CTRL)) { FoldAll(); } else {*/ int levelClick = ::SendMessage(_hWnd, SCI_GETFOLDLEVEL, lineClick, 0); if (levelClick & SC_FOLDLEVELHEADERFLAG) { if (modifiers & SCMOD_SHIFT) { // Ensure all children visible ::SendMessage(_hWnd, SCI_SETFOLDEXPANDED, lineClick, 1); Expand(lineClick, true, true, 100, levelClick); } else if (modifiers & SCMOD_CTRL) { if (::SendMessage(_hWnd, SCI_GETFOLDEXPANDED, lineClick, 0)) { // Contract this line and all children ::SendMessage(_hWnd, SCI_SETFOLDEXPANDED, lineClick, 0); Expand(lineClick, false, true, 0, levelClick); } else { // Expand this line and all children ::SendMessage(_hWnd, SCI_SETFOLDEXPANDED, lineClick, 1); Expand(lineClick, true, true, 100, levelClick); } } else { // Toggle this line ::SendMessage(_hWnd, SCI_TOGGLEFOLD, lineClick, 0); } } /* }*/ return true; } void CEditor::Expand(int &line, bool doExpand, bool force, int visLevels, int level){ int lineMaxSubord = ::SendMessage(_hWnd, SCI_GETLASTCHILD, line, level & SC_FOLDLEVELNUMBERMASK); line++; while (line <= lineMaxSubord) { if (force) { if (visLevels > 0) ::SendMessage(_hWnd, SCI_SHOWLINES, line, line); else ::SendMessage(_hWnd, SCI_HIDELINES, line, line); } else { if (doExpand) ::SendMessage(_hWnd, SCI_SHOWLINES, line, line); } int levelLine = level; if (levelLine == -1) levelLine = ::SendMessage(_hWnd, SCI_GETFOLDLEVEL, line, 0); if (levelLine & SC_FOLDLEVELHEADERFLAG) { if (force) { if (visLevels > 1) ::SendMessage(_hWnd, SCI_SETFOLDEXPANDED, line, 1); else ::SendMessage(_hWnd, SCI_SETFOLDEXPANDED, line, 0); Expand(line, doExpand, force, visLevels - 1); } else { if (doExpand) { if (!::SendMessage(_hWnd, SCI_GETFOLDEXPANDED, line, 0)) ::SendMessage(_hWnd, SCI_SETFOLDEXPANDED, line, 1); Expand(line, true, force, visLevels - 1); } else { Expand(line, false, force, visLevels - 1); } } } else { line++; } } }