Files
wxWidgets/samples/stc/edit.cpp
Maarten Bent 6eb357f038 Improve DPI handling in wxSTC
Adjusting the zoom level does not work correctly. It could lead to ever
increasing zoom.
Instead, set the correct DPI of the underlying device context.
2020-06-01 16:45:21 +02:00

1028 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)
// 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);
}
//! 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