wxWidgets/samples/stc/edit.cpp

1035 lines
35 KiB
C++

//////////////////////////////////////////////////////////////////////////////
// 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)
EVT_MENU(myID_TECHNOLOGY_DEFAULT, Edit::OnTechnology)
EVT_MENU(myID_TECHNOLOGY_DIRECTWRITE, Edit::OnTechnology)
// 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 = FromDIP(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);
}
void Edit::OnTechnology(wxCommandEvent& event)
{
SetTechnology(event.GetId() == myID_TECHNOLOGY_DIRECTWRITE ? wxSTC_TECHNOLOGY_DIRECTWRITE : wxSTC_TECHNOLOGY_DEFAULT);
}
//! 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<int> (page.x * ppiScr.x / 25.4);
page.y = static_cast<int> (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<int> (top * ppiScr.y / 25.4);
bottom = static_cast<int> (bottom * ppiScr.y / 25.4);
left = static_cast<int> (left * ppiScr.x / 25.4);
right = static_cast<int> (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