#ifndef SCINTILLAEDITCTRL_H #define SCINTILLAEDITCTRL_H #include #include "Scintilla.h" ///////////////////////////////////////////////////////////////////////////// // CScintillaEditCtrl window ///////////////////////////////////////////////////////////////////////////// /** * MFC wrapper for the scintilla control. */ typedef struct SCNotification NMSCINTILLAEDIT; extern const TCHAR WC_SCINTILLA[]; class CScintillaEditCtrl : public CWnd { DECLARE_DYNCREATE(CScintillaEditCtrl) ///@name Scintilla fast access data typedef int (*DIRECTFUNCTION)(void*,int,int,int); DIRECTFUNCTION m_fnDirect; ///< Function to access the message function directly void* m_pvDirect; ///< Direct pointer to Scintilla data static const char PIXMAP_FIRSTOPAQUEENTRY; static const char PIXMAP_TRANSPARENTENTRY; void ConvertPaletteToPixmap(CString& strPalette, CPalette* pPalette); void ConvertPixelsToPixmap(CString& strPixels, CSize& sizPixels, CDC& dcColor, CPalette* pPalette, const CDC& dcMask, COLORREF crefTransparent); /** * Converts a color HBITMAP with an HBITMAP mask or backround color to pixmap text. * Scintilla accepts both the C variable of arrays of pointers to chars (char* hicon[]) * or the string with the whole file contents (/* XPM .... ) * @param strPixmap String to return the pixmap text into * @param hbmColor HBITMAP with the color values. * @param hbmMask HBITMAP with the mask values. Can be set to NULL if there's no mask. * @param crefTransparent This color specifies the pixels * that will be treated as transparent from the mask HBITMAP. If the * mask HBITMAP is NULL, the color will be compared to the color HBITMAP value. * @note This function can only be called once the control has a suitable HDC */ void ConvertToPixmap(CString& strPixmap, HBITMAP hbmColor, HBITMAP hbmMask, COLORREF crefTransparent); /** * Converts the given HBITMAP to pixmap string. * Returns the pixmap string for this HBITMAP, using as transparent the given transparency * value. * @param strPixmap String to hold the pixmap text. * @param hbitmap HBITMAP to convert. * @param crefBackground Color to use as transparent. Two additional special values are * allowed: * - CREF_TOPLEFTPIXEL: The topleft pixel color value is used as transparency value. * - CREF_NONE: There are no transparent pixels in this bitmap. */ void ConvertToPixmap(CString& strPixmap, const HBITMAP hbitmap, COLORREF crefBackground = CREF_NONE) { ConvertToPixmap(strPixmap, hbitmap, NULL, crefBackground); } /** * Converts the given HICON to pixmap. * Returns the pixmap string for this HICON, using as transparent the given transparency * value. * @param strPixmap String to hold the pixmap text. * @param hicon HICON to convert to pixmap. * @param crefBackground COLORREF to test for transparency. If the pixel in the mask * matches this color, the pixel is regarded as transparent. Two additional * special values are allowed: * - CREF_TOPLEFTPIXEL: The icon mask is not used for transparency, instead the topleft * pixel from the icon color map is used as transparent color. * - CREF_NONE: The icon mask is not used and there are no transparent pixels in the icon. */ void ConvertToPixmap(CString& strPixmap, const HICON hicon, COLORREF crefBackground = RGB(0xFF, 0xFF, 0xFF)) { ICONINFO iconinfo; // Get the icon information (mask & color bitmaps) GetIconInfo(hicon, &iconinfo); ConvertToPixmap(strPixmap, iconinfo.hbmColor, iconinfo.hbmMask, crefBackground); } // Attributes public: // Operations public: // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CScintillaEditCtrl) //}}AFX_VIRTUAL // Generated message map functions protected: //{{AFX_MSG(CScintillaEditCtrl) // NOTE - the ClassWizard will add and remove member functions here. //}}AFX_MSG DECLARE_MESSAGE_MAP() public: static const TCHAR SCINTILLADLLNAME[]; typedef BYTE STYLE; typedef int HMARKER; ///< Marker handle typedef DWORD MARKERSET; ///< Set of markers static const HMARKER INVALIDHMARKER; ///@name COLORREF constants static const COLORREF CREF_NONE; ///< No color. static const COLORREF CREF_TOPLEFTPIXEL; ///< Transparent color from the topleft pixel. typedef struct { TCHAR cLetter; STYLE ubStyle; } STYLECHAR; enum EMarkerSymbol { MRKSYM_CIRCLE = SC_MARK_CIRCLE, MRKSYM_ROUNDRECT = SC_MARK_ROUNDRECT, MRKSYM_ARROW = SC_MARK_ARROW, MRKSYM_SMALLRECT = SC_MARK_SMALLRECT, MRKSYM_SHORTARROW = SC_MARK_SHORTARROW, MRKSYM_EMPTY = SC_MARK_EMPTY, MRKSYM_ARROWDOWN = SC_MARK_ARROWDOWN, MRKSYM_MINUS = SC_MARK_MINUS, MRKSYM_PLUS = SC_MARK_PLUS, MRKSYM_VLINE = SC_MARK_VLINE, MRKSYM_LCORNER = SC_MARK_LCORNER, MRKSYM_TCORNER = SC_MARK_TCORNER, MRKSYM_BOXPLUS = SC_MARK_BOXPLUS, MRKSYM_BOXPLUSCONNECTED = SC_MARK_BOXPLUSCONNECTED, MRKSYM_BOXMINUS = SC_MARK_BOXMINUS, MRKSYM_BOXMINUSCONNECTED = SC_MARK_BOXMINUSCONNECTED, MRKSYM_LCORNERCURVE = SC_MARK_LCORNERCURVE, MRKSYM_TCORNERCURVE = SC_MARK_TCORNERCURVE, MRKSYM_CIRCLEPLUS = SC_MARK_CIRCLEPLUS, MRKSYM_CIRCLEPLUSCONNECTED = SC_MARK_CIRCLEPLUSCONNECTED, MRKSYM_CIRCLEMINUS = SC_MARK_CIRCLEMINUS, MRKSYM_CIRCLEMINUSCONNECTED = SC_MARK_CIRCLEMINUSCONNECTED, MRKSYM_BACKGROUND = SC_MARK_BACKGROUND, MRKSYM_DOTDOTDOT = SC_MARK_DOTDOTDOT, MRKSYM_ARROWS = SC_MARK_ARROWS, MRKSYM_PIXMAP = SC_MARK_PIXMAP, MRKSYM_CHARACTER = SC_MARK_CHARACTER }; enum EIndicatorSymbol { INDSYM_PLAIN = INDIC_PLAIN, INDSYM_SQUIGGLE = INDIC_SQUIGGLE, INDSYM_TT = INDIC_TT, INDSYM_DIAGONAL = INDIC_DIAGONAL, INDSYM_STRIKE = INDIC_STRIKE }; CScintillaEditCtrl() { } BOOL CScintillaEditCtrl::Create(CRect* prect, CWnd* pParentWnd, int nId) { HINSTANCE hInst = GetModuleHandle(SCINTILLADLLNAME); m_hWnd = CreateWindowEx(0, WC_SCINTILLA,"", WS_CHILD | WS_TABSTOP | WS_VISIBLE | WS_CLIPSIBLINGS, 0,0,500,400,pParentWnd->m_hWnd,(HMENU)NULL, hInst, NULL); ASSERT(m_hWnd != NULL); if (m_hWnd != NULL) { // Initialize the direct pointers (Scintilla fast access mode). m_fnDirect = (DIRECTFUNCTION) SendMessage(SCI_GETDIRECTFUNCTION,0,0); m_pvDirect = (void *)SendMessage(SCI_GETDIRECTPOINTER,0,0); ASSERT(m_fnDirect != NULL && m_pvDirect != NULL); // Set the background color to the proper one (scintilla defaults to white) COLORREF crefBkgnd = GetSysColor(COLOR_WINDOW); SetStyleBackColor(STYLE_DEFAULT, crefBkgnd); // Reset all the styles to the default SetStyleClearAll(); } return (m_hWnd != NULL); } int SendSciMsg(UINT msg, WPARAM wParam=0, LPARAM lParam=0) { return m_fnDirect(m_pvDirect, msg, wParam, lParam); } virtual BOOL CScintillaEditCtrl::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext) { CRect rc = rect; return Create(&rc, pParentWnd, nID); } ///@name Text retrieval & manipulation /** * Fills the buffer with nLength characters, plus an extra NULL character. * @param nLength Number of characters to retrieve (not including NULL) * @param pszText Buffer of characters. * @note This routine differs from the lowlevel one, in the sense that it * takes nLength valid characters (not nLength-1) */ void GetText(int nLength, TCHAR *pszText) { // Note SCI_GETTEXT gets WPARAM-1 characters and appends the extra NULL SendSciMsg(SCI_GETTEXT, nLength+1, (LPARAM) pszText); } /** * Returns the first nLength characters of the buffer and appends a NULL at the end. * @param nLength Number of characters to fill the CString with (not including NULL). * @param str CString to return the text into. * @see GetText(int, TCHAR) */ void GetText(int nLength, CString& str) { // Allocate enough space in the string buffer // (not counting the NULL char, as GetBuffer does it for us) LPTSTR lpsz = str.GetBuffer(nLength); GetText(nLength+1, lpsz); str.ReleaseBuffer(nLength); } /** * Returns all the text of the control. * @param str CString to return the text into. */ void GetText(CString& str) { int nTextLength = GetTextLength(); // Get nTextLength valid chars GetText(nTextLength, str); } void SetText(TCHAR* pszText) { SendSciMsg(SCI_SETTEXT, 0, (LPARAM) pszText); } /** * Clears the modify flag. */ void SetSavePoint() { SendSciMsg(SCI_SETSAVEPOINT); } /** * Returns the text in the given line, including any end of line chars. * @param nLine Line to retrieve (1-based) * @param pszText Buffer of text to fill. * @note This function differs from the lowlevel message in the sense that lines * start by 1 and not zero. */ void GetLineText(int nLine, TCHAR* pszText) { SendSciMsg(SCI_GETLINE, nLine-1, (LPARAM) pszText); } void GetLineText(int nLine, CString& str) { int nLineLength = GetLineLength(nLine); LPTSTR lpsz = str.GetBuffer(nLineLength); GetLineText(nLine, lpsz); str.ReleaseBuffer(nLineLength); } void ReplaceSel(TCHAR* pszText) { SendSciMsg(SCI_REPLACESEL, 0, (LPARAM) pszText); } BOOL GetReadonly() { return SendSciMsg(SCI_GETREADONLY); } void SetReadonly(BOOL bReadonly) { SendSciMsg(SCI_SETREADONLY, bReadonly); } void GetTextRange(TEXTRANGE* pTextRange) { SendSciMsg(SCI_GETTEXTRANGE, 0, (LPARAM) pTextRange); } void AddText(int nLength, TCHAR* pszText) { SendSciMsg(SCI_ADDTEXT, nLength, (LPARAM) pszText); } void AddStyledText(int nLength, STYLECHAR* pscText) { SendSciMsg(SCI_ADDSTYLEDTEXT, nLength, (LPARAM) pscText); } /** * Appends nLength characters to the edit buffer (including any NULL it may have * in the middle). */ void AppendText(int nLength, const TCHAR* pszText) { SendSciMsg(SCI_APPENDTEXT, nLength, (LPARAM) pszText); } /** * Inserts the zero terminated text at position nPos. * @param nPos Position to insert the text from. If -1, the text is inserted * from the current position. The current position is updated to the end of * the text. * @param NULL terminated string to insert. * @todo The current position seems to remain at the start of the buffer :? */ void InsertText(int nPos, const TCHAR* pszText) { SendSciMsg(SCI_INSERTTEXT, nPos, (LPARAM) pszText); } /** * Clear the edit buffer. */ void ClearAll(void) { SendSciMsg(SCI_CLEARALL); } void ClearDocumentStyle(void) { SendSciMsg(SCI_CLEARDOCUMENTSTYLE); } TCHAR GetCharAt(int nPos) { return SendSciMsg(SCI_GETCHARAT, nPos); } STYLE GetStyleAt(int nPos) { SendSciMsg(SCI_GETSTYLEAT, nPos); } STYLECHAR* GetStyledText(TEXTRANGE* ptr) { return (STYLECHAR*) SendSciMsg(SCI_GETSTYLEDTEXT, 0, (LPARAM) ptr); } /** * Sets the number of style bits. * The remaining bits are used for indicators. Initially 5 bits are used for style and 3 for * indicators */ void SetStyleBits(int nBits = 5) { SendSciMsg(SCI_SETSTYLEBITS, nBits); } int GetStyleBits() { return SendSciMsg(SCI_GETSTYLEBITS); } ///@name Style functions void SetStyleForeColor(int nStyle, COLORREF clrColor) { SendSciMsg(SCI_STYLESETFORE, nStyle, clrColor); } void SetStyleBackColor(int nStyle, COLORREF clrColor) { SendSciMsg(SCI_STYLESETBACK, nStyle, clrColor); } void SetStyleBold(int nStyle, BOOL bBold) { SendSciMsg(SCI_STYLESETBOLD, nStyle, bBold); } void SetStyleItalic(int nStyle, BOOL bItalic) { SendSciMsg(SCI_STYLESETITALIC, nStyle, bItalic); } void SetStyleUnderline(int nStyle, BOOL bUnderline) { SendSciMsg(SCI_STYLESETUNDERLINE, nStyle, bUnderline); } void SetStyleSize(int nStyle, int nSizeInPts) { SendSciMsg(SCI_STYLESETSIZE, nStyle, nSizeInPts); } void SetStyleFont(int nStyle, TCHAR* pszFontName) { SendSciMsg(SCI_STYLESETFONT, nStyle, (LPARAM) pszFontName); } void SetStyleResetDefault() { SendSciMsg(SCI_STYLERESETDEFAULT); } void SetStyleClearAll() { SendSciMsg(SCI_STYLECLEARALL); } ///@name Style application /** * @return The last character formatted correctly */ int GetEndStyled() { return SendSciMsg(SCI_GETENDSTYLED); } void StartStyling(int nPos, int nMask) { SendSciMsg(SCI_STARTSTYLING, nPos, nMask); } /** * Sets the style of a string of text. * @param nLength Length of the text to set its style. * @param nStyle Style to set all the text to. */ void SetStyling(int nLength, int nStyle) { SendSciMsg(SCI_SETSTYLING, nLength, nStyle); } /** * Sets the style of a string of text. * @param nLength Length of the text & array of styles * @param styles Array of styles (one for each char of text). */ void SetStyling(int nLength, const char* styles) { SendSciMsg(SCI_SETSTYLINGEX, nLength, (LPARAM) styles); } ///@name Marker functions void DefineMarker(int nMarker, EMarkerSymbol mrksSymbol) { SendSciMsg(SCI_MARKERDEFINE, nMarker, mrksSymbol); } /** * Defines the given marker to be drawn as an ASCII letter */ void DefineMarker(int nMarker, char cAscii) { SendSciMsg(SCI_MARKERDEFINE, nMarker, cAscii+MRKSYM_CHARACTER); } /** * Defines the given marker as a HICON * @param nMarker Marker id. * @param hicon HICON to set the marker to. The icon is no needed * outside this function, so the app is free to release it at any time. * @param crefTransparent Color to use as transparent * @see ConvertToPixmap(CString&, HICON, COLORREF) */ void DefineMarker(int nMarker, const HICON hicon, COLORREF crefTransparent = RGB(0xFF, 0xFF, 0xFF)) { CString strPixmap; ConvertToPixmap(strPixmap, hicon, crefTransparent); SendSciMsg(SCI_MARKERDEFINEPIXMAP, nMarker, (LPARAM) ((LPCTSTR) strPixmap)); } /** * Defines the given marker as a HBITMAP * @param nMarker Marker id. * @param hbitmap HBITMAP to set the marker to. The bitmap is no needed * outside this function, so the app is free to release it at any time. * @param crefTransparent * @see ConvertToPixmap(CString&, HBITMAP, COLORREF) */ void DefineMarker(int nMarker, const HBITMAP hbitmap, COLORREF crefTransparent = CREF_NONE) { CString strPixmap; ConvertToPixmap(strPixmap, hbitmap, crefTransparent); SendSciMsg(SCI_MARKERDEFINEPIXMAP, nMarker, (LPARAM) ((LPCTSTR) strPixmap)); } /** * Sets the foreground color of the marker. */ void SetMarkerForeColor(int nMarker, COLORREF clrFore) { SendSciMsg(SCI_MARKERSETFORE, nMarker, clrFore); } /** * Sets the background color of the marker. */ void SetMarkerBackColor(int nMarker, COLORREF clrBack) { SendSciMsg(SCI_MARKERSETBACK, nMarker, clrBack); } /** * Marks the given line with a marker. * @return Returns a handle for the marker so it can be used with */ HMARKER AddMarker(int nLine, int nMarker) { return SendSciMsg(SCI_MARKERADD, nLine-1, nMarker); } /** * Returns a bitmask of all the markers in the given line */ DWORD GetMarkersMask(int nLine) { return SendSciMsg(SCI_MARKERGET, nLine-1); } BOOL LineIsMarked(int nLine, int nMarker) { DWORD dwMarkersMask = GetMarkersMask(nLine); return ((dwMarkersMask & (1 << nMarker)) != 0); } void ToggleMarker(int nLine, int nMarker) { if (LineIsMarked(nLine, nMarker)) { DeleteMarker(nLine, nMarker); } else { AddMarker(nLine, nMarker); } } /** * Returns the next line with at least one of the markers in the mask, -1 if not found. */ int GetNextMarkedLine(int nLineStart, MARKERSET dwMarkersMask) { return SendSciMsg(SCI_MARKERNEXT, nLineStart-1, dwMarkersMask); } /** * Returns the prev line with at least one of the markers in the mask, -1 if not found. */ int GetPrevMarkedLine(int nLineStart, MARKERSET dwMarkersMask) { return SendSciMsg(SCI_MARKERPREVIOUS, nLineStart-1, dwMarkersMask); } void DeleteAllMarker(int nMarker) { SendSciMsg(SCI_MARKERDELETEALL, nMarker); } /** * */ int GetMarkedLine(HMARKER hmarker) { return SendSciMsg(SCI_MARKERLINEFROMHANDLE, hmarker)+1; } /** * */ int DeleteMarker(HMARKER hmarker) { return SendSciMsg(SCI_MARKERDELETEHANDLE, hmarker); } void DeleteMarker(int nLine, int nMarker) { SendSciMsg(SCI_MARKERDELETE, nLine-1, nMarker); } ///@name Indicator functions void SetIndicatorSymbol(int nIndNumber, int nIndStyle) { SendSciMsg(SCI_INDICSETSTYLE, nIndNumber, nIndStyle); } EIndicatorSymbol GetIndicatorSymbol(int inIndNumber) { return (EIndicatorSymbol) SendSciMsg(SCI_INDICGETSTYLE); } void SetIndicatorForeColor(int nIndNumber, COLORREF clrFore) { SendSciMsg(SCI_INDICSETFORE, nIndNumber, clrFore); } COLORREF GetIndicatorForeColor(int nIndNumber) { return SendSciMsg(SCI_INDICGETFORE, nIndNumber); } ///@name Layout functions void SetMarginLeft(int nWidthInPix) { SendSciMsg(SCI_SETMARGINLEFT, 0, nWidthInPix); } int GetMarginLeft() { return SendSciMsg(SCI_GETMARGINLEFT); } void SetMarginRight(int nWidthInPix) { SendSciMsg(SCI_SETMARGINRIGHT, 0, nWidthInPix); } int GetMarginRight() { return SendSciMsg(SCI_GETMARGINRIGHT); } void SetMarginType(int nMargin, int nType) { SendSciMsg(SCI_SETMARGINTYPEN, nMargin, nType); } int GetMarginType(int nMargin) { return SendSciMsg(SCI_GETMARGINTYPEN, nMargin); } void SetMarginWidth(int nMargin, int nWidthInPix) { SendSciMsg(SCI_SETMARGINWIDTHN, nMargin, nWidthInPix); } int GetMarginWidth(int nMargin) { return SendSciMsg(SCI_GETMARGINWIDTHN, nMargin); } ///@name Selection & information /** * Returns the length of the buffer in characters. * This length does not include the final NULL character. * @return Length of the buffer in characters. */ int GetTextLength() { return SendSciMsg(SCI_GETTEXTLENGTH); } int GetLineCount() { return SendSciMsg(SCI_GETLINECOUNT); } int GetFirstVisibleLine() { return SendSciMsg(SCI_GETFIRSTVISIBLELINE)+1; } int GetLinesOnScreen() { return SendSciMsg(SCI_LINESONSCREEN); } int GetLineFromPosition(int nPosition) { return SendSciMsg(SCI_LINEFROMPOSITION, nPosition)+1; } int GetPositionFromLine(int nLine) { return SendSciMsg(SCI_POSITIONFROMLINE, nLine-1); } int GetLineLength(int nLine) { return SendSciMsg(SCI_LINELENGTH, nLine-1); } int GetLineEndPosition(int nLine) { return SendSciMsg(SCI_GETLINEENDPOSITION, nLine-1); } void GetSelectedText(TCHAR* pszText) { SendSciMsg(SCI_GETSELTEXT, 0, (LPARAM) pszText); } /** * Gets the text of the current line and the position of the caret inside the line. * @return The position of the caret inside the line */ int GetCurrentLineText(TCHAR* pszText, int nMaxLength) { return SendSciMsg(SCI_GETCURLINE, nMaxLength, (LPARAM) pszText); } int GetCurrentLine() { int nPos = GetCurrentPos(); return GetLineFromPosition(nPos); } BOOL GetModifiedFlag() { return SendSciMsg(SCI_GETMODIFY); } void SetSelectionStart(int nPosition) { SendSciMsg(SCI_SETSELECTIONSTART, nPosition); } int GetSelectionStart() { return SendSciMsg(SCI_GETSELECTIONSTART); } void SetSelectionEnd(int nPosition) { SendSciMsg(SCI_SETSELECTIONEND, nPosition); } int GetSelectionEnd() { return SendSciMsg(SCI_GETSELECTIONEND); } void SetCurrentPos(int nCurrentPos) { SendSciMsg(SCI_SETCURRENTPOS, nCurrentPos); } int GetCurrentPos() { return SendSciMsg(SCI_GETCURRENTPOS); } void GotoPos(int nPos) { SendSciMsg(SCI_GOTOPOS, nPos); } void GotoLine(int nLine) { SendSciMsg(SCI_GOTOLINE, nLine-1); } ///@name Cut, copy & paste BOOL CanCopyCut() { return ((GetSelectionEnd() - GetSelectionStart()) != 0); } BOOL CanPaste() { return SendSciMsg(SCI_CANPASTE); } void CopySelectionText() { SendSciMsg(SCI_COPY); } void PasteClipboardText() { SendSciMsg(SCI_PASTE); } void CutSelectionText() { SendSciMsg(SCI_CUT); } /// @name Undo/Redo BOOL CanUndo() { return SendSciMsg(SCI_CANUNDO); } void Undo() { SendSciMsg(SCI_UNDO); } BOOL CanRedo() { return SendSciMsg(SCI_CANREDO); } void Redo() { SendSciMsg(SCI_REDO); } void EmptyUndoBuffer() { SendSciMsg(SCI_EMPTYUNDOBUFFER); } virtual ~CScintillaEditCtrl() { DestroyWindow(); } }; BOOL AfxInitScintilla(void); #endif