////////////////////////////////////////////////////////////////////////////// // File: contrib/samples/stc/edit.cpp // Purpose: STC test module // Maintainer: Wyo // Created: 2003-09-01 // Copyright: (c) wxGuide // Licence: wxWindows licence ////////////////////////////////////////////////////////////////////////////// //---------------------------------------------------------------------------- // informations //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // headers //---------------------------------------------------------------------------- // For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif // for all others, include the necessary headers (this file is usually all you // need because it includes almost all 'standard' wxWidgets headers) #ifndef WX_PRECOMP #include "wx/wx.h" #include "wx/textdlg.h" #endif //! wxWidgets headers #include "wx/file.h" // raw file io support #include "wx/filename.h" // filename support //! application headers #include "defsext.h" // additional definitions #include "edit.h" // edit module //---------------------------------------------------------------------------- // resources //---------------------------------------------------------------------------- //============================================================================ // declarations //============================================================================ // The (uniform) style used for the annotations. const int ANNOTATION_STYLE = wxSTC_STYLE_LASTPREDEFINED + 1; // A small image of a hashtag symbol used in the autocompletion window. const char* hashtag_xpm[] = { "10 10 2 1", " c None", ". c #BD08F9", " .. .. ", " .. .. ", "..........", "..........", " .. .. ", " .. .. ", "..........", "..........", " .. .. ", " .. .. "}; //============================================================================ // implementation //============================================================================ //---------------------------------------------------------------------------- // Edit //---------------------------------------------------------------------------- wxBEGIN_EVENT_TABLE (Edit, wxStyledTextCtrl) // common EVT_SIZE ( Edit::OnSize) // edit EVT_MENU (wxID_CLEAR, Edit::OnEditClear) EVT_MENU (wxID_CUT, Edit::OnEditCut) EVT_MENU (wxID_COPY, Edit::OnEditCopy) EVT_MENU (wxID_PASTE, Edit::OnEditPaste) EVT_MENU (myID_INDENTINC, Edit::OnEditIndentInc) EVT_MENU (myID_INDENTRED, Edit::OnEditIndentRed) EVT_MENU (wxID_SELECTALL, Edit::OnEditSelectAll) EVT_MENU (myID_SELECTLINE, Edit::OnEditSelectLine) EVT_MENU (wxID_REDO, Edit::OnEditRedo) EVT_MENU (wxID_UNDO, Edit::OnEditUndo) // find EVT_MENU (wxID_FIND, Edit::OnFind) EVT_MENU (myID_FINDNEXT, Edit::OnFindNext) EVT_MENU (myID_REPLACE, Edit::OnReplace) EVT_MENU (myID_REPLACENEXT, Edit::OnReplaceNext) EVT_MENU (myID_BRACEMATCH, Edit::OnBraceMatch) EVT_MENU (myID_GOTO, Edit::OnGoto) // view EVT_MENU_RANGE (myID_HIGHLIGHTFIRST, myID_HIGHLIGHTLAST, Edit::OnHighlightLang) EVT_MENU (myID_DISPLAYEOL, Edit::OnDisplayEOL) EVT_MENU (myID_INDENTGUIDE, Edit::OnIndentGuide) EVT_MENU (myID_LINENUMBER, Edit::OnLineNumber) EVT_MENU (myID_LONGLINEON, Edit::OnLongLineOn) EVT_MENU (myID_WHITESPACE, Edit::OnWhiteSpace) EVT_MENU (myID_FOLDTOGGLE, Edit::OnFoldToggle) EVT_MENU (myID_OVERTYPE, Edit::OnSetOverType) EVT_MENU (myID_READONLY, Edit::OnSetReadOnly) EVT_MENU (myID_WRAPMODEON, Edit::OnWrapmodeOn) EVT_MENU (myID_CHARSETANSI, Edit::OnUseCharset) EVT_MENU (myID_CHARSETMAC, Edit::OnUseCharset) // annotations EVT_MENU (myID_ANNOTATION_ADD, Edit::OnAnnotationAdd) EVT_MENU (myID_ANNOTATION_REMOVE, Edit::OnAnnotationRemove) EVT_MENU (myID_ANNOTATION_CLEAR, Edit::OnAnnotationClear) EVT_MENU (myID_ANNOTATION_STYLE_HIDDEN, Edit::OnAnnotationStyle) EVT_MENU (myID_ANNOTATION_STYLE_STANDARD, Edit::OnAnnotationStyle) EVT_MENU (myID_ANNOTATION_STYLE_BOXED, Edit::OnAnnotationStyle) // extra EVT_MENU (myID_CHANGELOWER, Edit::OnChangeCase) EVT_MENU (myID_CHANGEUPPER, Edit::OnChangeCase) EVT_MENU (myID_CONVERTCR, Edit::OnConvertEOL) EVT_MENU (myID_CONVERTCRLF, Edit::OnConvertEOL) EVT_MENU (myID_CONVERTLF, Edit::OnConvertEOL) EVT_MENU(myID_MULTIPLE_SELECTIONS, Edit::OnMultipleSelections) EVT_MENU(myID_MULTI_PASTE, Edit::OnMultiPaste) EVT_MENU(myID_MULTIPLE_SELECTIONS_TYPING, Edit::OnMultipleSelectionsTyping) EVT_MENU(myID_CUSTOM_POPUP, Edit::OnCustomPopup) // stc EVT_STC_MARGINCLICK (wxID_ANY, Edit::OnMarginClick) EVT_STC_CHARADDED (wxID_ANY, Edit::OnCharAdded) EVT_STC_CALLTIP_CLICK(wxID_ANY, Edit::OnCallTipClick) EVT_KEY_DOWN( Edit::OnKeyDown ) wxEND_EVENT_TABLE() Edit::Edit (wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size, long style) : wxStyledTextCtrl (parent, id, pos, size, style) { m_LineNrID = 0; m_DividerID = 1; m_FoldingID = 2; // initialize language m_language = NULL; // default font for all styles SetViewEOL (g_CommonPrefs.displayEOLEnable); SetIndentationGuides (g_CommonPrefs.indentGuideEnable); SetEdgeMode (g_CommonPrefs.longLineOnEnable? wxSTC_EDGE_LINE: wxSTC_EDGE_NONE); SetViewWhiteSpace (g_CommonPrefs.whiteSpaceEnable? wxSTC_WS_VISIBLEALWAYS: wxSTC_WS_INVISIBLE); SetOvertype (g_CommonPrefs.overTypeInitial); SetReadOnly (g_CommonPrefs.readOnlyInitial); SetWrapMode (g_CommonPrefs.wrapModeInitial? wxSTC_WRAP_WORD: wxSTC_WRAP_NONE); wxFont font(wxFontInfo(10).Family(wxFONTFAMILY_MODERN)); StyleSetFont (wxSTC_STYLE_DEFAULT, font); StyleSetForeground (wxSTC_STYLE_DEFAULT, *wxBLACK); StyleSetBackground (wxSTC_STYLE_DEFAULT, *wxWHITE); StyleSetForeground (wxSTC_STYLE_LINENUMBER, wxColour ("DARK GREY")); StyleSetBackground (wxSTC_STYLE_LINENUMBER, *wxWHITE); StyleSetForeground(wxSTC_STYLE_INDENTGUIDE, wxColour ("DARK GREY")); InitializePrefs (DEFAULT_LANGUAGE); // set visibility SetVisiblePolicy (wxSTC_VISIBLE_STRICT|wxSTC_VISIBLE_SLOP, 1); SetXCaretPolicy (wxSTC_CARET_EVEN|wxSTC_VISIBLE_STRICT|wxSTC_CARET_SLOP, 1); SetYCaretPolicy (wxSTC_CARET_EVEN|wxSTC_VISIBLE_STRICT|wxSTC_CARET_SLOP, 1); // markers MarkerDefine (wxSTC_MARKNUM_FOLDER, wxSTC_MARK_DOTDOTDOT, "BLACK", "BLACK"); MarkerDefine (wxSTC_MARKNUM_FOLDEROPEN, wxSTC_MARK_ARROWDOWN, "BLACK", "BLACK"); MarkerDefine (wxSTC_MARKNUM_FOLDERSUB, wxSTC_MARK_EMPTY, "BLACK", "BLACK"); MarkerDefine (wxSTC_MARKNUM_FOLDEREND, wxSTC_MARK_DOTDOTDOT, "BLACK", "WHITE"); MarkerDefine (wxSTC_MARKNUM_FOLDEROPENMID, wxSTC_MARK_ARROWDOWN, "BLACK", "WHITE"); MarkerDefine (wxSTC_MARKNUM_FOLDERMIDTAIL, wxSTC_MARK_EMPTY, "BLACK", "BLACK"); MarkerDefine (wxSTC_MARKNUM_FOLDERTAIL, wxSTC_MARK_EMPTY, "BLACK", "BLACK"); // annotations AnnotationSetVisible(wxSTC_ANNOTATION_BOXED); // autocompletion wxBitmap bmp(hashtag_xpm); RegisterImage(0, bmp); // call tips CallTipSetBackground(*wxYELLOW); m_calltipNo = 1; // miscellaneous m_LineNrMargin = TextWidth (wxSTC_STYLE_LINENUMBER, "_999999"); m_FoldingMargin = 16; CmdKeyClear (wxSTC_KEY_TAB, 0); // this is done by the menu accelerator key SetLayoutCache (wxSTC_CACHE_PAGE); UsePopUp(wxSTC_POPUP_ALL); } Edit::~Edit () {} //---------------------------------------------------------------------------- // common event handlers void Edit::OnSize( wxSizeEvent& event ) { int x = GetClientSize().x + (g_CommonPrefs.lineNumberEnable? m_LineNrMargin: 0) + (g_CommonPrefs.foldEnable? m_FoldingMargin: 0); if (x > 0) SetScrollWidth (x); event.Skip(); } // edit event handlers void Edit::OnEditRedo (wxCommandEvent &WXUNUSED(event)) { if (!CanRedo()) return; Redo (); } void Edit::OnEditUndo (wxCommandEvent &WXUNUSED(event)) { if (!CanUndo()) return; Undo (); } void Edit::OnEditClear (wxCommandEvent &WXUNUSED(event)) { if (GetReadOnly()) return; Clear (); } void Edit::OnKeyDown (wxKeyEvent &event) { if (CallTipActive()) CallTipCancel(); if (event.GetKeyCode() == WXK_SPACE && event.ControlDown() && event.ShiftDown()) { // Show our first call tip at the current position of the caret. m_calltipNo = 1; ShowCallTipAt(GetCurrentPos()); return; } event.Skip(); } void Edit::OnEditCut (wxCommandEvent &WXUNUSED(event)) { if (GetReadOnly() || (GetSelectionEnd()-GetSelectionStart() <= 0)) return; Cut (); } void Edit::OnEditCopy (wxCommandEvent &WXUNUSED(event)) { if (GetSelectionEnd()-GetSelectionStart() <= 0) return; Copy (); } void Edit::OnEditPaste (wxCommandEvent &WXUNUSED(event)) { if (!CanPaste()) return; Paste (); } void Edit::OnFind (wxCommandEvent &WXUNUSED(event)) { } void Edit::OnFindNext (wxCommandEvent &WXUNUSED(event)) { } void Edit::OnReplace (wxCommandEvent &WXUNUSED(event)) { } void Edit::OnReplaceNext (wxCommandEvent &WXUNUSED(event)) { } void Edit::OnBraceMatch (wxCommandEvent &WXUNUSED(event)) { int min = GetCurrentPos (); int max = BraceMatch (min); if (max > (min+1)) { BraceHighlight (min+1, max); SetSelection (min+1, max); }else{ BraceBadLight (min); } } void Edit::OnGoto (wxCommandEvent &WXUNUSED(event)) { } void Edit::OnEditIndentInc (wxCommandEvent &WXUNUSED(event)) { CmdKeyExecute (wxSTC_CMD_TAB); } void Edit::OnEditIndentRed (wxCommandEvent &WXUNUSED(event)) { CmdKeyExecute (wxSTC_CMD_DELETEBACK); } void Edit::OnEditSelectAll (wxCommandEvent &WXUNUSED(event)) { SetSelection (0, GetTextLength ()); } void Edit::OnEditSelectLine (wxCommandEvent &WXUNUSED(event)) { int lineStart = PositionFromLine (GetCurrentLine()); int lineEnd = PositionFromLine (GetCurrentLine() + 1); SetSelection (lineStart, lineEnd); } void Edit::OnHighlightLang (wxCommandEvent &event) { InitializePrefs (g_LanguagePrefs [event.GetId() - myID_HIGHLIGHTFIRST].name); } void Edit::OnDisplayEOL (wxCommandEvent &WXUNUSED(event)) { SetViewEOL (!GetViewEOL()); } void Edit::OnIndentGuide (wxCommandEvent &WXUNUSED(event)) { SetIndentationGuides (!GetIndentationGuides()); } void Edit::OnLineNumber (wxCommandEvent &WXUNUSED(event)) { SetMarginWidth (m_LineNrID, GetMarginWidth (m_LineNrID) == 0? m_LineNrMargin: 0); } void Edit::OnLongLineOn (wxCommandEvent &WXUNUSED(event)) { SetEdgeMode (GetEdgeMode() == 0? wxSTC_EDGE_LINE: wxSTC_EDGE_NONE); } void Edit::OnWhiteSpace (wxCommandEvent &WXUNUSED(event)) { SetViewWhiteSpace (GetViewWhiteSpace() == 0? wxSTC_WS_VISIBLEALWAYS: wxSTC_WS_INVISIBLE); } void Edit::OnFoldToggle (wxCommandEvent &WXUNUSED(event)) { ToggleFold (GetFoldParent(GetCurrentLine())); } void Edit::OnSetOverType (wxCommandEvent &WXUNUSED(event)) { SetOvertype (!GetOvertype()); } void Edit::OnSetReadOnly (wxCommandEvent &WXUNUSED(event)) { SetReadOnly (!GetReadOnly()); } void Edit::OnWrapmodeOn (wxCommandEvent &WXUNUSED(event)) { SetWrapMode (GetWrapMode() == 0? wxSTC_WRAP_WORD: wxSTC_WRAP_NONE); } void Edit::OnUseCharset (wxCommandEvent &event) { int Nr; int charset = GetCodePage(); switch (event.GetId()) { case myID_CHARSETANSI: {charset = wxSTC_CHARSET_ANSI; break;} case myID_CHARSETMAC: {charset = wxSTC_CHARSET_ANSI; break;} } for (Nr = 0; Nr < wxSTC_STYLE_LASTPREDEFINED; Nr++) { StyleSetCharacterSet (Nr, charset); } SetCodePage (charset); } void Edit::OnAnnotationAdd(wxCommandEvent& WXUNUSED(event)) { const int line = GetCurrentLine(); wxString ann = AnnotationGetText(line); ann = wxGetTextFromUser ( wxString::Format("Enter annotation for the line %d", line), "Edit annotation", ann, this ); if ( ann.empty() ) return; AnnotationSetText(line, ann); AnnotationSetStyle(line, ANNOTATION_STYLE); // Scintilla doesn't update the scroll width for annotations, even with // scroll width tracking on, so do it manually. const int width = GetScrollWidth(); // NB: The following adjustments are only needed when using // wxSTC_ANNOTATION_BOXED annotations style, but we apply them always // in order to make things simpler and not have to redo the width // calculations when the annotations visibility changes. In a real // program you'd either just stick to a fixed annotations visibility or // update the width when it changes. // Take into account the fact that the annotation is shown indented, with // the same indent as the line it's attached to. int indent = GetLineIndentation(line); // This is just a hack to account for the width of the box, there doesn't // seem to be any way to get it directly from Scintilla. indent += 3; const int widthAnn = TextWidth(ANNOTATION_STYLE, ann + wxString(indent, ' ')); if (widthAnn > width) SetScrollWidth(widthAnn); } void Edit::OnAnnotationRemove(wxCommandEvent& WXUNUSED(event)) { AnnotationSetText(GetCurrentLine(), wxString()); } void Edit::OnAnnotationClear(wxCommandEvent& WXUNUSED(event)) { AnnotationClearAll(); } void Edit::OnAnnotationStyle(wxCommandEvent& event) { int style = 0; switch (event.GetId()) { case myID_ANNOTATION_STYLE_HIDDEN: style = wxSTC_ANNOTATION_HIDDEN; break; case myID_ANNOTATION_STYLE_STANDARD: style = wxSTC_ANNOTATION_STANDARD; break; case myID_ANNOTATION_STYLE_BOXED: style = wxSTC_ANNOTATION_BOXED; break; } AnnotationSetVisible(style); } void Edit::OnChangeCase (wxCommandEvent &event) { switch (event.GetId()) { case myID_CHANGELOWER: { CmdKeyExecute (wxSTC_CMD_LOWERCASE); break; } case myID_CHANGEUPPER: { CmdKeyExecute (wxSTC_CMD_UPPERCASE); break; } } } void Edit::OnConvertEOL (wxCommandEvent &event) { int eolMode = GetEOLMode(); switch (event.GetId()) { case myID_CONVERTCR: { eolMode = wxSTC_EOL_CR; break;} case myID_CONVERTCRLF: { eolMode = wxSTC_EOL_CRLF; break;} case myID_CONVERTLF: { eolMode = wxSTC_EOL_LF; break;} } ConvertEOLs (eolMode); SetEOLMode (eolMode); } void Edit::OnMultipleSelections(wxCommandEvent& WXUNUSED(event)) { bool isSet = GetMultipleSelection(); SetMultipleSelection(!isSet); } void Edit::OnMultiPaste(wxCommandEvent& WXUNUSED(event)) { int pasteMode = GetMultiPaste(); if (wxSTC_MULTIPASTE_EACH == pasteMode) { SetMultiPaste(wxSTC_MULTIPASTE_ONCE); } else { SetMultiPaste(wxSTC_MULTIPASTE_EACH); } } void Edit::OnMultipleSelectionsTyping(wxCommandEvent& WXUNUSED(event)) { bool isSet = GetAdditionalSelectionTyping(); SetAdditionalSelectionTyping(!isSet); } void Edit::OnCustomPopup(wxCommandEvent& evt) { UsePopUp(evt.IsChecked() ? wxSTC_POPUP_NEVER : wxSTC_POPUP_ALL); } //! misc void Edit::OnMarginClick (wxStyledTextEvent &event) { if (event.GetMargin() == 2) { int lineClick = LineFromPosition (event.GetPosition()); int levelClick = GetFoldLevel (lineClick); if ((levelClick & wxSTC_FOLDLEVELHEADERFLAG) > 0) { ToggleFold (lineClick); } } } void Edit::OnCharAdded (wxStyledTextEvent &event) { char chr = (char)event.GetKey(); int currentLine = GetCurrentLine(); // Change this if support for mac files with \r is needed if (chr == '\n') { int lineInd = 0; if (currentLine > 0) { lineInd = GetLineIndentation(currentLine - 1); } if (lineInd == 0) return; SetLineIndentation (currentLine, lineInd); GotoPos(PositionFromLine (currentLine) + lineInd); } else if (chr == '#') { wxString s = "define?0 elif?0 else?0 endif?0 error?0 if?0 ifdef?0 " "ifndef?0 include?0 line?0 pragma?0 undef?0"; AutoCompShow(0,s); } } void Edit::OnCallTipClick(wxStyledTextEvent &event) { if ( event.GetPosition() == 1 ) { // If position=1, the up arrow has been clicked. Show the next tip. m_calltipNo = m_calltipNo==3?1:(m_calltipNo+1); ShowCallTipAt(CallTipPosAtStart()); } else if ( event.GetPosition() == 2 ) { // If position=2, the down arrow has been clicked. Show previous tip. m_calltipNo = m_calltipNo==1?3:(m_calltipNo-1); ShowCallTipAt(CallTipPosAtStart()); } } //---------------------------------------------------------------------------- // private functions void Edit::ShowCallTipAt(int position) { // In a call tip string, the character '\001' will become a clickable // up arrow and '\002' will become a clickable down arrow. wxString ctString = wxString::Format("\001 %d of 3 \002 ", m_calltipNo); if ( m_calltipNo == 1 ) ctString += "This is a call tip. Try clicking the up or down buttons."; else if ( m_calltipNo == 2 ) ctString += "It is meant to be a context sensitive popup helper for " "the user."; else ctString += "This is a call tip with multiple lines.\n" "You can provide slightly longer help with " "call tips like these."; if ( CallTipActive() ) CallTipCancel(); CallTipShow(position, ctString); } wxString Edit::DeterminePrefs (const wxString &filename) { LanguageInfo const* curInfo; // determine language from filepatterns int languageNr; for (languageNr = 0; languageNr < g_LanguagePrefsSize; languageNr++) { curInfo = &g_LanguagePrefs [languageNr]; wxString filepattern = curInfo->filepattern; filepattern.Lower(); while (!filepattern.empty()) { wxString cur = filepattern.BeforeFirst (';'); if ((cur == filename) || (cur == (filename.BeforeLast ('.') + ".*")) || (cur == ("*." + filename.AfterLast ('.')))) { return curInfo->name; } filepattern = filepattern.AfterFirst (';'); } } return wxEmptyString; } bool Edit::InitializePrefs (const wxString &name) { // initialize styles StyleClearAll(); LanguageInfo const* curInfo = NULL; // determine language bool found = false; int languageNr; for (languageNr = 0; languageNr < g_LanguagePrefsSize; languageNr++) { curInfo = &g_LanguagePrefs [languageNr]; if (curInfo->name == name) { found = true; break; } } if (!found) return false; // set lexer and language SetLexer (curInfo->lexer); m_language = curInfo; // set margin for line numbers SetMarginType (m_LineNrID, wxSTC_MARGIN_NUMBER); StyleSetForeground (wxSTC_STYLE_LINENUMBER, wxColour ("DARK GREY")); StyleSetBackground (wxSTC_STYLE_LINENUMBER, *wxWHITE); SetMarginWidth (m_LineNrID, 0); // start out not visible // annotations style StyleSetBackground(ANNOTATION_STYLE, wxColour(244, 220, 220)); StyleSetForeground(ANNOTATION_STYLE, *wxBLACK); StyleSetSizeFractional(ANNOTATION_STYLE, (StyleGetSizeFractional(wxSTC_STYLE_DEFAULT)*4)/5); // default fonts for all styles! int Nr; for (Nr = 0; Nr < wxSTC_STYLE_LASTPREDEFINED; Nr++) { wxFont font(wxFontInfo(10).Family(wxFONTFAMILY_MODERN)); StyleSetFont (Nr, font); } // set common styles StyleSetForeground (wxSTC_STYLE_DEFAULT, wxColour ("DARK GREY")); StyleSetForeground (wxSTC_STYLE_INDENTGUIDE, wxColour ("DARK GREY")); // initialize settings if (g_CommonPrefs.syntaxEnable) { int keywordnr = 0; for (Nr = 0; Nr < STYLE_TYPES_COUNT; Nr++) { if (curInfo->styles[Nr].type == -1) continue; const StyleInfo &curType = g_StylePrefs [curInfo->styles[Nr].type]; wxFont font(wxFontInfo(curType.fontsize) .Family(wxFONTFAMILY_MODERN) .FaceName(curType.fontname)); StyleSetFont (Nr, font); if (curType.foreground.length()) { StyleSetForeground (Nr, wxColour (curType.foreground)); } if (curType.background.length()) { StyleSetBackground (Nr, wxColour (curType.background)); } StyleSetBold (Nr, (curType.fontstyle & mySTC_STYLE_BOLD) > 0); StyleSetItalic (Nr, (curType.fontstyle & mySTC_STYLE_ITALIC) > 0); StyleSetUnderline (Nr, (curType.fontstyle & mySTC_STYLE_UNDERL) > 0); StyleSetVisible (Nr, (curType.fontstyle & mySTC_STYLE_HIDDEN) == 0); StyleSetCase (Nr, curType.lettercase); const char *pwords = curInfo->styles[Nr].words; if (pwords) { SetKeyWords (keywordnr, pwords); keywordnr += 1; } } } // set margin as unused SetMarginType (m_DividerID, wxSTC_MARGIN_SYMBOL); SetMarginWidth (m_DividerID, 0); SetMarginSensitive (m_DividerID, false); // folding SetMarginType (m_FoldingID, wxSTC_MARGIN_SYMBOL); SetMarginMask (m_FoldingID, wxSTC_MASK_FOLDERS); StyleSetBackground (m_FoldingID, *wxWHITE); SetMarginWidth (m_FoldingID, 0); SetMarginSensitive (m_FoldingID, false); if (g_CommonPrefs.foldEnable) { SetMarginWidth (m_FoldingID, curInfo->folds != 0? m_FoldingMargin: 0); SetMarginSensitive (m_FoldingID, curInfo->folds != 0); SetProperty ("fold", curInfo->folds != 0? "1": "0"); SetProperty ("fold.comment", (curInfo->folds & mySTC_FOLD_COMMENT) > 0? "1": "0"); SetProperty ("fold.compact", (curInfo->folds & mySTC_FOLD_COMPACT) > 0? "1": "0"); SetProperty ("fold.preprocessor", (curInfo->folds & mySTC_FOLD_PREPROC) > 0? "1": "0"); SetProperty ("fold.html", (curInfo->folds & mySTC_FOLD_HTML) > 0? "1": "0"); SetProperty ("fold.html.preprocessor", (curInfo->folds & mySTC_FOLD_HTMLPREP) > 0? "1": "0"); SetProperty ("fold.comment.python", (curInfo->folds & mySTC_FOLD_COMMENTPY) > 0? "1": "0"); SetProperty ("fold.quotes.python", (curInfo->folds & mySTC_FOLD_QUOTESPY) > 0? "1": "0"); } SetFoldFlags (wxSTC_FOLDFLAG_LINEBEFORE_CONTRACTED | wxSTC_FOLDFLAG_LINEAFTER_CONTRACTED); // set spaces and indentation SetTabWidth (4); SetUseTabs (false); SetTabIndents (true); SetBackSpaceUnIndents (true); SetIndent (g_CommonPrefs.indentEnable? 4: 0); // others SetViewEOL (g_CommonPrefs.displayEOLEnable); SetIndentationGuides (g_CommonPrefs.indentGuideEnable); SetEdgeColumn (80); SetEdgeMode (g_CommonPrefs.longLineOnEnable? wxSTC_EDGE_LINE: wxSTC_EDGE_NONE); SetViewWhiteSpace (g_CommonPrefs.whiteSpaceEnable? wxSTC_WS_VISIBLEALWAYS: wxSTC_WS_INVISIBLE); SetOvertype (g_CommonPrefs.overTypeInitial); SetReadOnly (g_CommonPrefs.readOnlyInitial); SetWrapMode (g_CommonPrefs.wrapModeInitial? wxSTC_WRAP_WORD: wxSTC_WRAP_NONE); return true; } bool Edit::LoadFile () { #if wxUSE_FILEDLG // get filename if (!m_filename) { wxFileDialog dlg (this, "Open file", wxEmptyString, wxEmptyString, "Any file (*)|*", wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_CHANGE_DIR); if (dlg.ShowModal() != wxID_OK) return false; m_filename = dlg.GetPath(); } // load file return LoadFile (m_filename); #else return false; #endif // wxUSE_FILEDLG } bool Edit::LoadFile (const wxString &filename) { // load file in edit and clear undo if (!filename.empty()) m_filename = filename; wxStyledTextCtrl::LoadFile(m_filename); EmptyUndoBuffer(); // determine lexer language wxFileName fname (m_filename); InitializePrefs (DeterminePrefs (fname.GetFullName())); return true; } bool Edit::SaveFile () { #if wxUSE_FILEDLG // return if no change if (!Modified()) return true; // get filename if (!m_filename) { wxFileDialog dlg (this, "Save file", wxEmptyString, wxEmptyString, "Any file (*)|*", wxFD_SAVE | wxFD_OVERWRITE_PROMPT); if (dlg.ShowModal() != wxID_OK) return false; m_filename = dlg.GetPath(); } // save file return SaveFile (m_filename); #else return false; #endif // wxUSE_FILEDLG } bool Edit::SaveFile (const wxString &filename) { // return if no change if (!Modified()) return true; // // save edit in file and clear undo // if (!filename.empty()) m_filename = filename; // wxFile file (m_filename, wxFile::write); // if (!file.IsOpened()) return false; // wxString buf = GetText(); // bool okay = file.Write (buf); // file.Close(); // if (!okay) return false; // EmptyUndoBuffer(); // SetSavePoint(); // return true; return wxStyledTextCtrl::SaveFile(filename); } bool Edit::Modified () { // return modified state return (GetModify() && !GetReadOnly()); } //---------------------------------------------------------------------------- // EditProperties //---------------------------------------------------------------------------- EditProperties::EditProperties (Edit *edit, long style) : wxDialog (edit, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, style | wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) { // sets the application title SetTitle (_("Properties")); wxString text; // full name wxBoxSizer *fullname = new wxBoxSizer (wxHORIZONTAL); fullname->Add (10, 0); fullname->Add (new wxStaticText (this, wxID_ANY, _("Full filename"), wxDefaultPosition, wxSize(80, wxDefaultCoord)), 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL); fullname->Add (new wxStaticText (this, wxID_ANY, edit->GetFilename()), 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL); // text info wxGridSizer *textinfo = new wxGridSizer (4, 0, 2); textinfo->Add (new wxStaticText (this, wxID_ANY, _("Language"), wxDefaultPosition, wxSize(80, wxDefaultCoord)), 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxLEFT, 4); textinfo->Add (new wxStaticText (this, wxID_ANY, edit->m_language->name), 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxRIGHT, 4); textinfo->Add (new wxStaticText (this, wxID_ANY, _("Lexer-ID: "), wxDefaultPosition, wxSize(80, wxDefaultCoord)), 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxLEFT, 4); text = wxString::Format ("%d", edit->GetLexer()); textinfo->Add (new wxStaticText (this, wxID_ANY, text), 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxRIGHT, 4); wxString EOLtype; switch (edit->GetEOLMode()) { case wxSTC_EOL_CR: {EOLtype = "CR (Unix)"; break; } case wxSTC_EOL_CRLF: {EOLtype = "CRLF (Windows)"; break; } case wxSTC_EOL_LF: {EOLtype = "CR (Macintosh)"; break; } } textinfo->Add (new wxStaticText (this, wxID_ANY, _("Line endings"), wxDefaultPosition, wxSize(80, wxDefaultCoord)), 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxLEFT, 4); textinfo->Add (new wxStaticText (this, wxID_ANY, EOLtype), 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxRIGHT, 4); // text info box wxStaticBoxSizer *textinfos = new wxStaticBoxSizer ( new wxStaticBox (this, wxID_ANY, _("Information")), wxVERTICAL); textinfos->Add (textinfo, 0, wxEXPAND); textinfos->Add (0, 6); // statistic wxGridSizer *statistic = new wxGridSizer (4, 0, 2); statistic->Add (new wxStaticText (this, wxID_ANY, _("Total lines"), wxDefaultPosition, wxSize(80, wxDefaultCoord)), 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxLEFT, 4); text = wxString::Format ("%d", edit->GetLineCount()); statistic->Add (new wxStaticText (this, wxID_ANY, text), 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxRIGHT, 4); statistic->Add (new wxStaticText (this, wxID_ANY, _("Total chars"), wxDefaultPosition, wxSize(80, wxDefaultCoord)), 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxLEFT, 4); text = wxString::Format ("%d", edit->GetTextLength()); statistic->Add (new wxStaticText (this, wxID_ANY, text), 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxRIGHT, 4); statistic->Add (new wxStaticText (this, wxID_ANY, _("Current line"), wxDefaultPosition, wxSize(80, wxDefaultCoord)), 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxLEFT, 4); text = wxString::Format ("%d", edit->GetCurrentLine()); statistic->Add (new wxStaticText (this, wxID_ANY, text), 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxRIGHT, 4); statistic->Add (new wxStaticText (this, wxID_ANY, _("Current pos"), wxDefaultPosition, wxSize(80, wxDefaultCoord)), 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxLEFT, 4); text = wxString::Format ("%d", edit->GetCurrentPos()); statistic->Add (new wxStaticText (this, wxID_ANY, text), 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxRIGHT, 4); // char/line statistics wxStaticBoxSizer *statistics = new wxStaticBoxSizer ( new wxStaticBox (this, wxID_ANY, _("Statistics")), wxVERTICAL); statistics->Add (statistic, 0, wxEXPAND); statistics->Add (0, 6); // total pane wxBoxSizer *totalpane = new wxBoxSizer (wxVERTICAL); totalpane->Add (fullname, 0, wxEXPAND | wxLEFT | wxRIGHT | wxTOP, 10); totalpane->Add (0, 6); totalpane->Add (textinfos, 0, wxEXPAND | wxLEFT | wxRIGHT, 10); totalpane->Add (0, 10); totalpane->Add (statistics, 0, wxEXPAND | wxLEFT | wxRIGHT, 10); totalpane->Add (0, 6); wxButton *okButton = new wxButton (this, wxID_OK, _("OK")); okButton->SetDefault(); totalpane->Add (okButton, 0, wxALIGN_CENTER | wxALL, 10); SetSizerAndFit (totalpane); ShowModal(); } #if wxUSE_PRINTING_ARCHITECTURE //---------------------------------------------------------------------------- // EditPrint //---------------------------------------------------------------------------- EditPrint::EditPrint (Edit *edit, const wxString& title) : wxPrintout(title) , m_edit(edit) { } bool EditPrint::OnPrintPage (int page) { wxDC *dc = GetDC(); if (!dc) return false; // scale DC PrintScaling (dc); // print page m_edit->FormatRange(true, page == 1 ? 0 : m_pageEnds[page-2], m_pageEnds[page-1], dc, dc, m_printRect, m_pageRect); return true; } bool EditPrint::OnBeginDocument (int startPage, int endPage) { if (!wxPrintout::OnBeginDocument (startPage, endPage)) { return false; } return true; } void EditPrint::GetPageInfo (int *minPage, int *maxPage, int *selPageFrom, int *selPageTo) { // initialize values *minPage = 0; *maxPage = 0; *selPageFrom = 0; *selPageTo = 0; // scale DC if possible wxDC *dc = GetDC(); if (!dc) return; PrintScaling (dc); // get print page informations and convert to printer pixels wxSize ppiScr; GetPPIScreen (&ppiScr.x, &ppiScr.y); wxSize page = g_pageSetupData->GetPaperSize(); page.x = static_cast (page.x * ppiScr.x / 25.4); page.y = static_cast (page.y * ppiScr.y / 25.4); // In landscape mode we need to swap the width and height if ( g_pageSetupData->GetPrintData().GetOrientation() == wxLANDSCAPE ) { wxSwap(page.x, page.y); } m_pageRect = wxRect (0, 0, page.x, page.y); // get margins informations and convert to printer pixels wxPoint pt = g_pageSetupData->GetMarginTopLeft(); int left = pt.x; int top = pt.y; pt = g_pageSetupData->GetMarginBottomRight(); int right = pt.x; int bottom = pt.y; top = static_cast (top * ppiScr.y / 25.4); bottom = static_cast (bottom * ppiScr.y / 25.4); left = static_cast (left * ppiScr.x / 25.4); right = static_cast (right * ppiScr.x / 25.4); m_printRect = wxRect (left, top, page.x - (left + right), page.y - (top + bottom)); // count pages m_pageEnds.Clear(); int printed = 0; while ( printed < m_edit->GetLength() ) { printed = m_edit->FormatRange(false, printed, m_edit->GetLength(), dc, dc, m_printRect, m_pageRect); m_pageEnds.Add(printed); *maxPage += 1; } if (*maxPage > 0) *minPage = 1; *selPageFrom = *minPage; *selPageTo = *maxPage; } bool EditPrint::HasPage (int page) { return page <= (int)m_pageEnds.Count(); } bool EditPrint::PrintScaling (wxDC *dc){ // check for dc, return if none if (!dc) return false; // get printer and screen sizing values wxSize ppiScr; GetPPIScreen (&ppiScr.x, &ppiScr.y); if (ppiScr.x == 0) { // most possible guess 96 dpi ppiScr.x = 96; ppiScr.y = 96; } wxSize ppiPrt; GetPPIPrinter (&ppiPrt.x, &ppiPrt.y); if (ppiPrt.x == 0) { // scaling factor to 1 ppiPrt.x = ppiScr.x; ppiPrt.y = ppiScr.y; } wxSize dcSize = dc->GetSize(); wxSize pageSize; GetPageSizePixels (&pageSize.x, &pageSize.y); // set user scale float scale_x = (float)(ppiPrt.x * dcSize.x) / (float)(ppiScr.x * pageSize.x); float scale_y = (float)(ppiPrt.y * dcSize.y) / (float)(ppiScr.y * pageSize.y); dc->SetUserScale (scale_x, scale_y); return true; } #endif // wxUSE_PRINTING_ARCHITECTURE