1 //////////////////////////////////////////////////////////////////////////////
2 // File:        contrib/samples/stc/edit.cpp
3 // Purpose:     STC test module
4 // Maintainer:  Wyo
5 // Created:     2003-09-01
6 // Copyright:   (c) wxGuide
7 // Licence:     wxWindows licence
8 //////////////////////////////////////////////////////////////////////////////
9 
10 //----------------------------------------------------------------------------
11 // informations
12 //----------------------------------------------------------------------------
13 
14 
15 //----------------------------------------------------------------------------
16 // headers
17 //----------------------------------------------------------------------------
18 
19 // For compilers that support precompilation, includes "wx/wx.h".
20 #include "wx/wxprec.h"
21 
22 #ifdef __BORLANDC__
23     #pragma hdrstop
24 #endif
25 
26 // for all others, include the necessary headers (this file is usually all you
27 // need because it includes almost all 'standard' wxWidgets headers)
28 #ifndef WX_PRECOMP
29     #include "wx/wx.h"
30     #include "wx/textdlg.h"
31 #endif
32 
33 //! wxWidgets headers
34 #include "wx/file.h"     // raw file io support
35 #include "wx/filename.h" // filename support
36 
37 //! application headers
38 #include "defsext.h"     // additional definitions
39 
40 #include "edit.h"        // edit module
41 
42 
43 //----------------------------------------------------------------------------
44 // resources
45 //----------------------------------------------------------------------------
46 
47 
48 //============================================================================
49 // declarations
50 //============================================================================
51 
52 // The (uniform) style used for the annotations.
53 const int ANNOTATION_STYLE = wxSTC_STYLE_LASTPREDEFINED + 1;
54 
55 //============================================================================
56 // implementation
57 //============================================================================
58 
59 //----------------------------------------------------------------------------
60 // Edit
61 //----------------------------------------------------------------------------
62 
wxBEGIN_EVENT_TABLE(Edit,wxStyledTextCtrl)63 wxBEGIN_EVENT_TABLE (Edit, wxStyledTextCtrl)
64     // common
65     EVT_SIZE (                         Edit::OnSize)
66     // edit
67     EVT_MENU (wxID_CLEAR,              Edit::OnEditClear)
68     EVT_MENU (wxID_CUT,                Edit::OnEditCut)
69     EVT_MENU (wxID_COPY,               Edit::OnEditCopy)
70     EVT_MENU (wxID_PASTE,              Edit::OnEditPaste)
71     EVT_MENU (myID_INDENTINC,          Edit::OnEditIndentInc)
72     EVT_MENU (myID_INDENTRED,          Edit::OnEditIndentRed)
73     EVT_MENU (wxID_SELECTALL,          Edit::OnEditSelectAll)
74     EVT_MENU (myID_SELECTLINE,         Edit::OnEditSelectLine)
75     EVT_MENU (wxID_REDO,               Edit::OnEditRedo)
76     EVT_MENU (wxID_UNDO,               Edit::OnEditUndo)
77     // find
78     EVT_MENU (wxID_FIND,               Edit::OnFind)
79     EVT_MENU (myID_FINDNEXT,           Edit::OnFindNext)
80     EVT_MENU (myID_REPLACE,            Edit::OnReplace)
81     EVT_MENU (myID_REPLACENEXT,        Edit::OnReplaceNext)
82     EVT_MENU (myID_BRACEMATCH,         Edit::OnBraceMatch)
83     EVT_MENU (myID_GOTO,               Edit::OnGoto)
84     // view
85     EVT_MENU_RANGE (myID_HILIGHTFIRST, myID_HILIGHTLAST,
86                                        Edit::OnHilightLang)
87     EVT_MENU (myID_DISPLAYEOL,         Edit::OnDisplayEOL)
88     EVT_MENU (myID_INDENTGUIDE,        Edit::OnIndentGuide)
89     EVT_MENU (myID_LINENUMBER,         Edit::OnLineNumber)
90     EVT_MENU (myID_LONGLINEON,         Edit::OnLongLineOn)
91     EVT_MENU (myID_WHITESPACE,         Edit::OnWhiteSpace)
92     EVT_MENU (myID_FOLDTOGGLE,         Edit::OnFoldToggle)
93     EVT_MENU (myID_OVERTYPE,           Edit::OnSetOverType)
94     EVT_MENU (myID_READONLY,           Edit::OnSetReadOnly)
95     EVT_MENU (myID_WRAPMODEON,         Edit::OnWrapmodeOn)
96     EVT_MENU (myID_CHARSETANSI,        Edit::OnUseCharset)
97     EVT_MENU (myID_CHARSETMAC,         Edit::OnUseCharset)
98     // annotations
99     EVT_MENU (myID_ANNOTATION_ADD,     Edit::OnAnnotationAdd)
100     EVT_MENU (myID_ANNOTATION_REMOVE,  Edit::OnAnnotationRemove)
101     EVT_MENU (myID_ANNOTATION_CLEAR,   Edit::OnAnnotationClear)
102     EVT_MENU (myID_ANNOTATION_STYLE_HIDDEN,   Edit::OnAnnotationStyle)
103     EVT_MENU (myID_ANNOTATION_STYLE_STANDARD, Edit::OnAnnotationStyle)
104     EVT_MENU (myID_ANNOTATION_STYLE_BOXED,    Edit::OnAnnotationStyle)
105     // extra
106     EVT_MENU (myID_CHANGELOWER,        Edit::OnChangeCase)
107     EVT_MENU (myID_CHANGEUPPER,        Edit::OnChangeCase)
108     EVT_MENU (myID_CONVERTCR,          Edit::OnConvertEOL)
109     EVT_MENU (myID_CONVERTCRLF,        Edit::OnConvertEOL)
110     EVT_MENU (myID_CONVERTLF,          Edit::OnConvertEOL)
111     // stc
112     EVT_STC_MARGINCLICK (wxID_ANY,     Edit::OnMarginClick)
113     EVT_STC_CHARADDED (wxID_ANY,       Edit::OnCharAdded)
114     EVT_STC_KEY( wxID_ANY , Edit::OnKey )
115 
116     EVT_KEY_DOWN( Edit::OnKeyDown )
117 wxEND_EVENT_TABLE()
118 
119 Edit::Edit (wxWindow *parent, wxWindowID id,
120             const wxPoint &pos,
121             const wxSize &size,
122             long style)
123     : wxStyledTextCtrl (parent, id, pos, size, style) {
124 
125     m_filename = wxEmptyString;
126 
127     m_LineNrID = 0;
128     m_DividerID = 1;
129     m_FoldingID = 2;
130 
131     // initialize language
132     m_language = NULL;
133 
134     // Use all the bits in the style byte as styles, not indicators.
135     SetStyleBits(8);
136 
137     // default font for all styles
138     SetViewEOL (g_CommonPrefs.displayEOLEnable);
139     SetIndentationGuides (g_CommonPrefs.indentGuideEnable);
140     SetEdgeMode (g_CommonPrefs.longLineOnEnable?
141                  wxSTC_EDGE_LINE: wxSTC_EDGE_NONE);
142     SetViewWhiteSpace (g_CommonPrefs.whiteSpaceEnable?
143                        wxSTC_WS_VISIBLEALWAYS: wxSTC_WS_INVISIBLE);
144     SetOvertype (g_CommonPrefs.overTypeInitial);
145     SetReadOnly (g_CommonPrefs.readOnlyInitial);
146     SetWrapMode (g_CommonPrefs.wrapModeInitial?
147                  wxSTC_WRAP_WORD: wxSTC_WRAP_NONE);
148     wxFont font (10, wxMODERN, wxNORMAL, wxNORMAL);
149     StyleSetFont (wxSTC_STYLE_DEFAULT, font);
150     StyleSetForeground (wxSTC_STYLE_DEFAULT, *wxBLACK);
151     StyleSetBackground (wxSTC_STYLE_DEFAULT, *wxWHITE);
152     StyleSetForeground (wxSTC_STYLE_LINENUMBER, wxColour (wxT("DARK GREY")));
153     StyleSetBackground (wxSTC_STYLE_LINENUMBER, *wxWHITE);
154     StyleSetForeground(wxSTC_STYLE_INDENTGUIDE, wxColour (wxT("DARK GREY")));
155     InitializePrefs (DEFAULT_LANGUAGE);
156 
157     // set visibility
158     SetVisiblePolicy (wxSTC_VISIBLE_STRICT|wxSTC_VISIBLE_SLOP, 1);
159     SetXCaretPolicy (wxSTC_CARET_EVEN|wxSTC_VISIBLE_STRICT|wxSTC_CARET_SLOP, 1);
160     SetYCaretPolicy (wxSTC_CARET_EVEN|wxSTC_VISIBLE_STRICT|wxSTC_CARET_SLOP, 1);
161 
162     // markers
163     MarkerDefine (wxSTC_MARKNUM_FOLDER,        wxSTC_MARK_DOTDOTDOT, wxT("BLACK"), wxT("BLACK"));
164     MarkerDefine (wxSTC_MARKNUM_FOLDEROPEN,    wxSTC_MARK_ARROWDOWN, wxT("BLACK"), wxT("BLACK"));
165     MarkerDefine (wxSTC_MARKNUM_FOLDERSUB,     wxSTC_MARK_EMPTY,     wxT("BLACK"), wxT("BLACK"));
166     MarkerDefine (wxSTC_MARKNUM_FOLDEREND,     wxSTC_MARK_DOTDOTDOT, wxT("BLACK"), wxT("WHITE"));
167     MarkerDefine (wxSTC_MARKNUM_FOLDEROPENMID, wxSTC_MARK_ARROWDOWN, wxT("BLACK"), wxT("WHITE"));
168     MarkerDefine (wxSTC_MARKNUM_FOLDERMIDTAIL, wxSTC_MARK_EMPTY,     wxT("BLACK"), wxT("BLACK"));
169     MarkerDefine (wxSTC_MARKNUM_FOLDERTAIL,    wxSTC_MARK_EMPTY,     wxT("BLACK"), wxT("BLACK"));
170 
171     // annotations
172     AnnotationSetVisible(wxSTC_ANNOTATION_BOXED);
173 
174     // miscellaneous
175     m_LineNrMargin = TextWidth (wxSTC_STYLE_LINENUMBER, wxT("_999999"));
176     m_FoldingMargin = 16;
177     CmdKeyClear (wxSTC_KEY_TAB, 0); // this is done by the menu accelerator key
178     SetLayoutCache (wxSTC_CACHE_PAGE);
179 
180 }
181 
~Edit()182 Edit::~Edit () {}
183 
184 //----------------------------------------------------------------------------
185 // common event handlers
OnSize(wxSizeEvent & event)186 void Edit::OnSize( wxSizeEvent& event ) {
187     int x = GetClientSize().x +
188             (g_CommonPrefs.lineNumberEnable? m_LineNrMargin: 0) +
189             (g_CommonPrefs.foldEnable? m_FoldingMargin: 0);
190     if (x > 0) SetScrollWidth (x);
191     event.Skip();
192 }
193 
194 // edit event handlers
OnEditRedo(wxCommandEvent & WXUNUSED (event))195 void Edit::OnEditRedo (wxCommandEvent &WXUNUSED(event)) {
196     if (!CanRedo()) return;
197     Redo ();
198 }
199 
OnEditUndo(wxCommandEvent & WXUNUSED (event))200 void Edit::OnEditUndo (wxCommandEvent &WXUNUSED(event)) {
201     if (!CanUndo()) return;
202     Undo ();
203 }
204 
OnEditClear(wxCommandEvent & WXUNUSED (event))205 void Edit::OnEditClear (wxCommandEvent &WXUNUSED(event)) {
206     if (GetReadOnly()) return;
207     Clear ();
208 }
209 
OnKey(wxStyledTextEvent & WXUNUSED (event))210 void Edit::OnKey (wxStyledTextEvent &WXUNUSED(event))
211 {
212     wxMessageBox("OnKey");
213 }
214 
OnKeyDown(wxKeyEvent & event)215 void Edit::OnKeyDown (wxKeyEvent &event)
216 {
217     if (CallTipActive())
218         CallTipCancel();
219     if (event.GetKeyCode() == WXK_SPACE && event.ControlDown() && event.ShiftDown())
220     {
221         int pos = GetCurrentPos();
222         CallTipSetBackground(*wxYELLOW);
223         CallTipShow(pos,
224                     "This is a CallTip with multiple lines.\n"
225                     "It is meant to be a context sensitive popup helper for the user.");
226         return;
227     }
228     event.Skip();
229 }
230 
OnEditCut(wxCommandEvent & WXUNUSED (event))231 void Edit::OnEditCut (wxCommandEvent &WXUNUSED(event)) {
232     if (GetReadOnly() || (GetSelectionEnd()-GetSelectionStart() <= 0)) return;
233     Cut ();
234 }
235 
OnEditCopy(wxCommandEvent & WXUNUSED (event))236 void Edit::OnEditCopy (wxCommandEvent &WXUNUSED(event)) {
237     if (GetSelectionEnd()-GetSelectionStart() <= 0) return;
238     Copy ();
239 }
240 
OnEditPaste(wxCommandEvent & WXUNUSED (event))241 void Edit::OnEditPaste (wxCommandEvent &WXUNUSED(event)) {
242     if (!CanPaste()) return;
243     Paste ();
244 }
245 
OnFind(wxCommandEvent & WXUNUSED (event))246 void Edit::OnFind (wxCommandEvent &WXUNUSED(event)) {
247 }
248 
OnFindNext(wxCommandEvent & WXUNUSED (event))249 void Edit::OnFindNext (wxCommandEvent &WXUNUSED(event)) {
250 }
251 
OnReplace(wxCommandEvent & WXUNUSED (event))252 void Edit::OnReplace (wxCommandEvent &WXUNUSED(event)) {
253 }
254 
OnReplaceNext(wxCommandEvent & WXUNUSED (event))255 void Edit::OnReplaceNext (wxCommandEvent &WXUNUSED(event)) {
256 }
257 
OnBraceMatch(wxCommandEvent & WXUNUSED (event))258 void Edit::OnBraceMatch (wxCommandEvent &WXUNUSED(event)) {
259     int min = GetCurrentPos ();
260     int max = BraceMatch (min);
261     if (max > (min+1)) {
262         BraceHighlight (min+1, max);
263         SetSelection (min+1, max);
264     }else{
265         BraceBadLight (min);
266     }
267 }
268 
OnGoto(wxCommandEvent & WXUNUSED (event))269 void Edit::OnGoto (wxCommandEvent &WXUNUSED(event)) {
270 }
271 
OnEditIndentInc(wxCommandEvent & WXUNUSED (event))272 void Edit::OnEditIndentInc (wxCommandEvent &WXUNUSED(event)) {
273     CmdKeyExecute (wxSTC_CMD_TAB);
274 }
275 
OnEditIndentRed(wxCommandEvent & WXUNUSED (event))276 void Edit::OnEditIndentRed (wxCommandEvent &WXUNUSED(event)) {
277     CmdKeyExecute (wxSTC_CMD_DELETEBACK);
278 }
279 
OnEditSelectAll(wxCommandEvent & WXUNUSED (event))280 void Edit::OnEditSelectAll (wxCommandEvent &WXUNUSED(event)) {
281     SetSelection (0, GetTextLength ());
282 }
283 
OnEditSelectLine(wxCommandEvent & WXUNUSED (event))284 void Edit::OnEditSelectLine (wxCommandEvent &WXUNUSED(event)) {
285     int lineStart = PositionFromLine (GetCurrentLine());
286     int lineEnd = PositionFromLine (GetCurrentLine() + 1);
287     SetSelection (lineStart, lineEnd);
288 }
289 
OnHilightLang(wxCommandEvent & event)290 void Edit::OnHilightLang (wxCommandEvent &event) {
291     InitializePrefs (g_LanguagePrefs [event.GetId() - myID_HILIGHTFIRST].name);
292 }
293 
OnDisplayEOL(wxCommandEvent & WXUNUSED (event))294 void Edit::OnDisplayEOL (wxCommandEvent &WXUNUSED(event)) {
295     SetViewEOL (!GetViewEOL());
296 }
297 
OnIndentGuide(wxCommandEvent & WXUNUSED (event))298 void Edit::OnIndentGuide (wxCommandEvent &WXUNUSED(event)) {
299     SetIndentationGuides (!GetIndentationGuides());
300 }
301 
OnLineNumber(wxCommandEvent & WXUNUSED (event))302 void Edit::OnLineNumber (wxCommandEvent &WXUNUSED(event)) {
303     SetMarginWidth (m_LineNrID,
304                     GetMarginWidth (m_LineNrID) == 0? m_LineNrMargin: 0);
305 }
306 
OnLongLineOn(wxCommandEvent & WXUNUSED (event))307 void Edit::OnLongLineOn (wxCommandEvent &WXUNUSED(event)) {
308     SetEdgeMode (GetEdgeMode() == 0? wxSTC_EDGE_LINE: wxSTC_EDGE_NONE);
309 }
310 
OnWhiteSpace(wxCommandEvent & WXUNUSED (event))311 void Edit::OnWhiteSpace (wxCommandEvent &WXUNUSED(event)) {
312     SetViewWhiteSpace (GetViewWhiteSpace() == 0?
313                        wxSTC_WS_VISIBLEALWAYS: wxSTC_WS_INVISIBLE);
314 }
315 
OnFoldToggle(wxCommandEvent & WXUNUSED (event))316 void Edit::OnFoldToggle (wxCommandEvent &WXUNUSED(event)) {
317     ToggleFold (GetFoldParent(GetCurrentLine()));
318 }
319 
OnSetOverType(wxCommandEvent & WXUNUSED (event))320 void Edit::OnSetOverType (wxCommandEvent &WXUNUSED(event)) {
321     SetOvertype (!GetOvertype());
322 }
323 
OnSetReadOnly(wxCommandEvent & WXUNUSED (event))324 void Edit::OnSetReadOnly (wxCommandEvent &WXUNUSED(event)) {
325     SetReadOnly (!GetReadOnly());
326 }
327 
OnWrapmodeOn(wxCommandEvent & WXUNUSED (event))328 void Edit::OnWrapmodeOn (wxCommandEvent &WXUNUSED(event)) {
329     SetWrapMode (GetWrapMode() == 0? wxSTC_WRAP_WORD: wxSTC_WRAP_NONE);
330 }
331 
OnUseCharset(wxCommandEvent & event)332 void Edit::OnUseCharset (wxCommandEvent &event) {
333     int Nr;
334     int charset = GetCodePage();
335     switch (event.GetId()) {
336         case myID_CHARSETANSI: {charset = wxSTC_CHARSET_ANSI; break;}
337         case myID_CHARSETMAC: {charset = wxSTC_CHARSET_ANSI; break;}
338     }
339     for (Nr = 0; Nr < wxSTC_STYLE_LASTPREDEFINED; Nr++) {
340         StyleSetCharacterSet (Nr, charset);
341     }
342     SetCodePage (charset);
343 }
344 
OnAnnotationAdd(wxCommandEvent & WXUNUSED (event))345 void Edit::OnAnnotationAdd(wxCommandEvent& WXUNUSED(event))
346 {
347     const int line = GetCurrentLine();
348 
349     wxString ann = AnnotationGetText(line);
350     ann = wxGetTextFromUser
351           (
352             wxString::Format("Enter annotation for the line %d", line),
353             "Edit annotation",
354             ann,
355             this
356           );
357     if ( ann.empty() )
358         return;
359 
360     AnnotationSetText(line, ann);
361     AnnotationSetStyle(line, ANNOTATION_STYLE);
362 
363     // Scintilla doesn't update the scroll width for annotations, even with
364     // scroll width tracking on, so do it manually.
365     const int width = GetScrollWidth();
366 
367     // NB: The following adjustments are only needed when using
368     //     wxSTC_ANNOTATION_BOXED annotations style, but we apply them always
369     //     in order to make things simpler and not have to redo the width
370     //     calculations when the annotations visibility changes. In a real
371     //     program you'd either just stick to a fixed annotations visibility or
372     //     update the width when it changes.
373 
374     // Take into account the fact that the annotation is shown indented, with
375     // the same indent as the line it's attached to.
376     int indent = GetLineIndentation(line);
377 
378     // This is just a hack to account for the width of the box, there doesn't
379     // seem to be any way to get it directly from Scintilla.
380     indent += 3;
381 
382     const int widthAnn = TextWidth(ANNOTATION_STYLE, ann + wxString(indent, ' '));
383 
384     if (widthAnn > width)
385         SetScrollWidth(widthAnn);
386 }
387 
OnAnnotationRemove(wxCommandEvent & WXUNUSED (event))388 void Edit::OnAnnotationRemove(wxCommandEvent& WXUNUSED(event))
389 {
390     AnnotationSetText(GetCurrentLine(), wxString());
391 }
392 
OnAnnotationClear(wxCommandEvent & WXUNUSED (event))393 void Edit::OnAnnotationClear(wxCommandEvent& WXUNUSED(event))
394 {
395     AnnotationClearAll();
396 }
397 
OnAnnotationStyle(wxCommandEvent & event)398 void Edit::OnAnnotationStyle(wxCommandEvent& event)
399 {
400     int style = 0;
401     switch (event.GetId()) {
402         case myID_ANNOTATION_STYLE_HIDDEN:
403             style = wxSTC_ANNOTATION_HIDDEN;
404             break;
405 
406         case myID_ANNOTATION_STYLE_STANDARD:
407             style = wxSTC_ANNOTATION_STANDARD;
408             break;
409 
410         case myID_ANNOTATION_STYLE_BOXED:
411             style = wxSTC_ANNOTATION_BOXED;
412             break;
413     }
414 
415     AnnotationSetVisible(style);
416 }
417 
OnChangeCase(wxCommandEvent & event)418 void Edit::OnChangeCase (wxCommandEvent &event) {
419     switch (event.GetId()) {
420         case myID_CHANGELOWER: {
421             CmdKeyExecute (wxSTC_CMD_LOWERCASE);
422             break;
423         }
424         case myID_CHANGEUPPER: {
425             CmdKeyExecute (wxSTC_CMD_UPPERCASE);
426             break;
427         }
428     }
429 }
430 
OnConvertEOL(wxCommandEvent & event)431 void Edit::OnConvertEOL (wxCommandEvent &event) {
432     int eolMode = GetEOLMode();
433     switch (event.GetId()) {
434         case myID_CONVERTCR: { eolMode = wxSTC_EOL_CR; break;}
435         case myID_CONVERTCRLF: { eolMode = wxSTC_EOL_CRLF; break;}
436         case myID_CONVERTLF: { eolMode = wxSTC_EOL_LF; break;}
437     }
438     ConvertEOLs (eolMode);
439     SetEOLMode (eolMode);
440 }
441 
442 //! misc
OnMarginClick(wxStyledTextEvent & event)443 void Edit::OnMarginClick (wxStyledTextEvent &event) {
444     if (event.GetMargin() == 2) {
445         int lineClick = LineFromPosition (event.GetPosition());
446         int levelClick = GetFoldLevel (lineClick);
447         if ((levelClick & wxSTC_FOLDLEVELHEADERFLAG) > 0) {
448             ToggleFold (lineClick);
449         }
450     }
451 }
452 
OnCharAdded(wxStyledTextEvent & event)453 void Edit::OnCharAdded (wxStyledTextEvent &event) {
454     char chr = (char)event.GetKey();
455     int currentLine = GetCurrentLine();
456     // Change this if support for mac files with \r is needed
457     if (chr == '\n') {
458         int lineInd = 0;
459         if (currentLine > 0) {
460             lineInd = GetLineIndentation(currentLine - 1);
461         }
462         if (lineInd == 0) return;
463         SetLineIndentation (currentLine, lineInd);
464         GotoPos(PositionFromLine (currentLine) + lineInd);
465     }
466 }
467 
468 
469 //----------------------------------------------------------------------------
470 // private functions
DeterminePrefs(const wxString & filename)471 wxString Edit::DeterminePrefs (const wxString &filename) {
472 
473     LanguageInfo const* curInfo;
474 
475     // determine language from filepatterns
476     int languageNr;
477     for (languageNr = 0; languageNr < g_LanguagePrefsSize; languageNr++) {
478         curInfo = &g_LanguagePrefs [languageNr];
479         wxString filepattern = curInfo->filepattern;
480         filepattern.Lower();
481         while (!filepattern.empty()) {
482             wxString cur = filepattern.BeforeFirst (';');
483             if ((cur == filename) ||
484                 (cur == (filename.BeforeLast ('.') + wxT(".*"))) ||
485                 (cur == (wxT("*.") + filename.AfterLast ('.')))) {
486                 return curInfo->name;
487             }
488             filepattern = filepattern.AfterFirst (';');
489         }
490     }
491     return wxEmptyString;
492 
493 }
494 
InitializePrefs(const wxString & name)495 bool Edit::InitializePrefs (const wxString &name) {
496 
497     // initialize styles
498     StyleClearAll();
499     LanguageInfo const* curInfo = NULL;
500 
501     // determine language
502     bool found = false;
503     int languageNr;
504     for (languageNr = 0; languageNr < g_LanguagePrefsSize; languageNr++) {
505         curInfo = &g_LanguagePrefs [languageNr];
506         if (curInfo->name == name) {
507             found = true;
508             break;
509         }
510     }
511     if (!found) return false;
512 
513     // set lexer and language
514     SetLexer (curInfo->lexer);
515     m_language = curInfo;
516 
517     // set margin for line numbers
518     SetMarginType (m_LineNrID, wxSTC_MARGIN_NUMBER);
519     StyleSetForeground (wxSTC_STYLE_LINENUMBER, wxColour (wxT("DARK GREY")));
520     StyleSetBackground (wxSTC_STYLE_LINENUMBER, *wxWHITE);
521     SetMarginWidth (m_LineNrID, 0); // start out not visible
522 
523     // annotations style
524     StyleSetBackground(ANNOTATION_STYLE, wxColour(244, 220, 220));
525     StyleSetForeground(ANNOTATION_STYLE, *wxBLACK);
526     StyleSetSizeFractional(ANNOTATION_STYLE,
527             (StyleGetSizeFractional(wxSTC_STYLE_DEFAULT)*4)/5);
528 
529     // default fonts for all styles!
530     int Nr;
531     for (Nr = 0; Nr < wxSTC_STYLE_LASTPREDEFINED; Nr++) {
532         wxFont font (10, wxMODERN, wxNORMAL, wxNORMAL);
533         StyleSetFont (Nr, font);
534     }
535 
536     // set common styles
537     StyleSetForeground (wxSTC_STYLE_DEFAULT, wxColour (wxT("DARK GREY")));
538     StyleSetForeground (wxSTC_STYLE_INDENTGUIDE, wxColour (wxT("DARK GREY")));
539 
540     // initialize settings
541     if (g_CommonPrefs.syntaxEnable) {
542         int keywordnr = 0;
543         for (Nr = 0; Nr < STYLE_TYPES_COUNT; Nr++) {
544             if (curInfo->styles[Nr].type == -1) continue;
545             const StyleInfo &curType = g_StylePrefs [curInfo->styles[Nr].type];
546             wxFont font (curType.fontsize, wxMODERN, wxNORMAL, wxNORMAL, false,
547                          curType.fontname);
548             StyleSetFont (Nr, font);
549             if (curType.foreground) {
550                 StyleSetForeground (Nr, wxColour (curType.foreground));
551             }
552             if (curType.background) {
553                 StyleSetBackground (Nr, wxColour (curType.background));
554             }
555             StyleSetBold (Nr, (curType.fontstyle & mySTC_STYLE_BOLD) > 0);
556             StyleSetItalic (Nr, (curType.fontstyle & mySTC_STYLE_ITALIC) > 0);
557             StyleSetUnderline (Nr, (curType.fontstyle & mySTC_STYLE_UNDERL) > 0);
558             StyleSetVisible (Nr, (curType.fontstyle & mySTC_STYLE_HIDDEN) == 0);
559             StyleSetCase (Nr, curType.lettercase);
560             const char *pwords = curInfo->styles[Nr].words;
561             if (pwords) {
562                 SetKeyWords (keywordnr, pwords);
563                 keywordnr += 1;
564             }
565         }
566     }
567 
568     // set margin as unused
569     SetMarginType (m_DividerID, wxSTC_MARGIN_SYMBOL);
570     SetMarginWidth (m_DividerID, 0);
571     SetMarginSensitive (m_DividerID, false);
572 
573     // folding
574     SetMarginType (m_FoldingID, wxSTC_MARGIN_SYMBOL);
575     SetMarginMask (m_FoldingID, wxSTC_MASK_FOLDERS);
576     StyleSetBackground (m_FoldingID, *wxWHITE);
577     SetMarginWidth (m_FoldingID, 0);
578     SetMarginSensitive (m_FoldingID, false);
579     if (g_CommonPrefs.foldEnable) {
580         SetMarginWidth (m_FoldingID, curInfo->folds != 0? m_FoldingMargin: 0);
581         SetMarginSensitive (m_FoldingID, curInfo->folds != 0);
582         SetProperty (wxT("fold"), curInfo->folds != 0? wxT("1"): wxT("0"));
583         SetProperty (wxT("fold.comment"),
584                      (curInfo->folds & mySTC_FOLD_COMMENT) > 0? wxT("1"): wxT("0"));
585         SetProperty (wxT("fold.compact"),
586                      (curInfo->folds & mySTC_FOLD_COMPACT) > 0? wxT("1"): wxT("0"));
587         SetProperty (wxT("fold.preprocessor"),
588                      (curInfo->folds & mySTC_FOLD_PREPROC) > 0? wxT("1"): wxT("0"));
589         SetProperty (wxT("fold.html"),
590                      (curInfo->folds & mySTC_FOLD_HTML) > 0? wxT("1"): wxT("0"));
591         SetProperty (wxT("fold.html.preprocessor"),
592                      (curInfo->folds & mySTC_FOLD_HTMLPREP) > 0? wxT("1"): wxT("0"));
593         SetProperty (wxT("fold.comment.python"),
594                      (curInfo->folds & mySTC_FOLD_COMMENTPY) > 0? wxT("1"): wxT("0"));
595         SetProperty (wxT("fold.quotes.python"),
596                      (curInfo->folds & mySTC_FOLD_QUOTESPY) > 0? wxT("1"): wxT("0"));
597     }
598     SetFoldFlags (wxSTC_FOLDFLAG_LINEBEFORE_CONTRACTED |
599                   wxSTC_FOLDFLAG_LINEAFTER_CONTRACTED);
600 
601     // set spaces and indention
602     SetTabWidth (4);
603     SetUseTabs (false);
604     SetTabIndents (true);
605     SetBackSpaceUnIndents (true);
606     SetIndent (g_CommonPrefs.indentEnable? 4: 0);
607 
608     // others
609     SetViewEOL (g_CommonPrefs.displayEOLEnable);
610     SetIndentationGuides (g_CommonPrefs.indentGuideEnable);
611     SetEdgeColumn (80);
612     SetEdgeMode (g_CommonPrefs.longLineOnEnable? wxSTC_EDGE_LINE: wxSTC_EDGE_NONE);
613     SetViewWhiteSpace (g_CommonPrefs.whiteSpaceEnable?
614                        wxSTC_WS_VISIBLEALWAYS: wxSTC_WS_INVISIBLE);
615     SetOvertype (g_CommonPrefs.overTypeInitial);
616     SetReadOnly (g_CommonPrefs.readOnlyInitial);
617     SetWrapMode (g_CommonPrefs.wrapModeInitial?
618                  wxSTC_WRAP_WORD: wxSTC_WRAP_NONE);
619 
620     return true;
621 }
622 
LoadFile()623 bool Edit::LoadFile ()
624 {
625 #if wxUSE_FILEDLG
626     // get filname
627     if (!m_filename) {
628         wxFileDialog dlg (this, wxT("Open file"), wxEmptyString, wxEmptyString,
629                           wxT("Any file (*)|*"), wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_CHANGE_DIR);
630         if (dlg.ShowModal() != wxID_OK) return false;
631         m_filename = dlg.GetPath();
632     }
633 
634     // load file
635     return LoadFile (m_filename);
636 #else
637     return false;
638 #endif // wxUSE_FILEDLG
639 }
640 
LoadFile(const wxString & filename)641 bool Edit::LoadFile (const wxString &filename) {
642 
643     // load file in edit and clear undo
644     if (!filename.empty()) m_filename = filename;
645 
646     wxStyledTextCtrl::LoadFile(m_filename);
647 
648     EmptyUndoBuffer();
649 
650     // determine lexer language
651     wxFileName fname (m_filename);
652     InitializePrefs (DeterminePrefs (fname.GetFullName()));
653 
654     return true;
655 }
656 
SaveFile()657 bool Edit::SaveFile ()
658 {
659 #if wxUSE_FILEDLG
660     // return if no change
661     if (!Modified()) return true;
662 
663     // get filname
664     if (!m_filename) {
665         wxFileDialog dlg (this, wxT("Save file"), wxEmptyString, wxEmptyString, wxT("Any file (*)|*"),
666                           wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
667         if (dlg.ShowModal() != wxID_OK) return false;
668         m_filename = dlg.GetPath();
669     }
670 
671     // save file
672     return SaveFile (m_filename);
673 #else
674     return false;
675 #endif // wxUSE_FILEDLG
676 }
677 
SaveFile(const wxString & filename)678 bool Edit::SaveFile (const wxString &filename) {
679 
680     // return if no change
681     if (!Modified()) return true;
682 
683 //     // save edit in file and clear undo
684 //     if (!filename.empty()) m_filename = filename;
685 //     wxFile file (m_filename, wxFile::write);
686 //     if (!file.IsOpened()) return false;
687 //     wxString buf = GetText();
688 //     bool okay = file.Write (buf);
689 //     file.Close();
690 //     if (!okay) return false;
691 //     EmptyUndoBuffer();
692 //     SetSavePoint();
693 
694 //     return true;
695 
696     return wxStyledTextCtrl::SaveFile(filename);
697 
698 }
699 
Modified()700 bool Edit::Modified () {
701 
702     // return modified state
703     return (GetModify() && !GetReadOnly());
704 }
705 
706 //----------------------------------------------------------------------------
707 // EditProperties
708 //----------------------------------------------------------------------------
709 
EditProperties(Edit * edit,long style)710 EditProperties::EditProperties (Edit *edit,
711                                 long style)
712         : wxDialog (edit, wxID_ANY, wxEmptyString,
713                     wxDefaultPosition, wxDefaultSize,
714                     style | wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) {
715 
716     // sets the application title
717     SetTitle (_("Properties"));
718     wxString text;
719 
720     // fullname
721     wxBoxSizer *fullname = new wxBoxSizer (wxHORIZONTAL);
722     fullname->Add (10, 0);
723     fullname->Add (new wxStaticText (this, wxID_ANY, _("Full filename"),
724                                      wxDefaultPosition, wxSize(80, wxDefaultCoord)),
725                    0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL);
726     fullname->Add (new wxStaticText (this, wxID_ANY, edit->GetFilename()),
727                    0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL);
728 
729     // text info
730     wxGridSizer *textinfo = new wxGridSizer (4, 0, 2);
731     textinfo->Add (new wxStaticText (this, wxID_ANY, _("Language"),
732                                      wxDefaultPosition, wxSize(80, wxDefaultCoord)),
733                    0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxLEFT, 4);
734     textinfo->Add (new wxStaticText (this, wxID_ANY, edit->m_language->name),
735                    0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxRIGHT, 4);
736     textinfo->Add (new wxStaticText (this, wxID_ANY, _("Lexer-ID: "),
737                                      wxDefaultPosition, wxSize(80, wxDefaultCoord)),
738                    0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxLEFT, 4);
739     text = wxString::Format (wxT("%d"), edit->GetLexer());
740     textinfo->Add (new wxStaticText (this, wxID_ANY, text),
741                    0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxRIGHT, 4);
742     wxString EOLtype = wxEmptyString;
743     switch (edit->GetEOLMode()) {
744         case wxSTC_EOL_CR: {EOLtype = wxT("CR (Unix)"); break; }
745         case wxSTC_EOL_CRLF: {EOLtype = wxT("CRLF (Windows)"); break; }
746         case wxSTC_EOL_LF: {EOLtype = wxT("CR (Macintosh)"); break; }
747     }
748     textinfo->Add (new wxStaticText (this, wxID_ANY, _("Line endings"),
749                                      wxDefaultPosition, wxSize(80, wxDefaultCoord)),
750                    0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxLEFT, 4);
751     textinfo->Add (new wxStaticText (this, wxID_ANY, EOLtype),
752                    0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxRIGHT, 4);
753 
754     // text info box
755     wxStaticBoxSizer *textinfos = new wxStaticBoxSizer (
756                      new wxStaticBox (this, wxID_ANY, _("Informations")),
757                      wxVERTICAL);
758     textinfos->Add (textinfo, 0, wxEXPAND);
759     textinfos->Add (0, 6);
760 
761     // statistic
762     wxGridSizer *statistic = new wxGridSizer (4, 0, 2);
763     statistic->Add (new wxStaticText (this, wxID_ANY, _("Total lines"),
764                                      wxDefaultPosition, wxSize(80, wxDefaultCoord)),
765                     0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxLEFT, 4);
766     text = wxString::Format (wxT("%d"), edit->GetLineCount());
767     statistic->Add (new wxStaticText (this, wxID_ANY, text),
768                     0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxRIGHT, 4);
769     statistic->Add (new wxStaticText (this, wxID_ANY, _("Total chars"),
770                                      wxDefaultPosition, wxSize(80, wxDefaultCoord)),
771                     0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxLEFT, 4);
772     text = wxString::Format (wxT("%d"), edit->GetTextLength());
773     statistic->Add (new wxStaticText (this, wxID_ANY, text),
774                     0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxRIGHT, 4);
775     statistic->Add (new wxStaticText (this, wxID_ANY, _("Current line"),
776                                      wxDefaultPosition, wxSize(80, wxDefaultCoord)),
777                     0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxLEFT, 4);
778     text = wxString::Format (wxT("%d"), edit->GetCurrentLine());
779     statistic->Add (new wxStaticText (this, wxID_ANY, text),
780                     0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxRIGHT, 4);
781     statistic->Add (new wxStaticText (this, wxID_ANY, _("Current pos"),
782                                      wxDefaultPosition, wxSize(80, wxDefaultCoord)),
783                     0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxLEFT, 4);
784     text = wxString::Format (wxT("%d"), edit->GetCurrentPos());
785     statistic->Add (new wxStaticText (this, wxID_ANY, text),
786                     0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxRIGHT, 4);
787 
788     // char/line statistics
789     wxStaticBoxSizer *statistics = new wxStaticBoxSizer (
790                      new wxStaticBox (this, wxID_ANY, _("Statistics")),
791                      wxVERTICAL);
792     statistics->Add (statistic, 0, wxEXPAND);
793     statistics->Add (0, 6);
794 
795     // total pane
796     wxBoxSizer *totalpane = new wxBoxSizer (wxVERTICAL);
797     totalpane->Add (fullname, 0, wxEXPAND | wxLEFT | wxRIGHT | wxTOP, 10);
798     totalpane->Add (0, 6);
799     totalpane->Add (textinfos, 0, wxEXPAND | wxLEFT | wxRIGHT, 10);
800     totalpane->Add (0, 10);
801     totalpane->Add (statistics, 0, wxEXPAND | wxLEFT | wxRIGHT, 10);
802     totalpane->Add (0, 6);
803     wxButton *okButton = new wxButton (this, wxID_OK, _("OK"));
804     okButton->SetDefault();
805     totalpane->Add (okButton, 0, wxALIGN_CENTER | wxALL, 10);
806 
807     SetSizerAndFit (totalpane);
808 
809     ShowModal();
810 }
811 
812 #if wxUSE_PRINTING_ARCHITECTURE
813 
814 //----------------------------------------------------------------------------
815 // EditPrint
816 //----------------------------------------------------------------------------
817 
EditPrint(Edit * edit,const wxChar * title)818 EditPrint::EditPrint (Edit *edit, const wxChar *title)
819               : wxPrintout(title) {
820     m_edit = edit;
821     m_printed = 0;
822 
823 }
824 
OnPrintPage(int page)825 bool EditPrint::OnPrintPage (int page) {
826 
827     wxDC *dc = GetDC();
828     if (!dc) return false;
829 
830     // scale DC
831     PrintScaling (dc);
832 
833     // print page
834     if (page == 1) m_printed = 0;
835     m_printed = m_edit->FormatRange (1, m_printed, m_edit->GetLength(),
836                                      dc, dc, m_printRect, m_pageRect);
837 
838     return true;
839 }
840 
OnBeginDocument(int startPage,int endPage)841 bool EditPrint::OnBeginDocument (int startPage, int endPage) {
842 
843     if (!wxPrintout::OnBeginDocument (startPage, endPage)) {
844         return false;
845     }
846 
847     return true;
848 }
849 
GetPageInfo(int * minPage,int * maxPage,int * selPageFrom,int * selPageTo)850 void EditPrint::GetPageInfo (int *minPage, int *maxPage, int *selPageFrom, int *selPageTo) {
851 
852     // initialize values
853     *minPage = 0;
854     *maxPage = 0;
855     *selPageFrom = 0;
856     *selPageTo = 0;
857 
858     // scale DC if possible
859     wxDC *dc = GetDC();
860     if (!dc) return;
861     PrintScaling (dc);
862 
863     // get print page informations and convert to printer pixels
864     wxSize ppiScr;
865     GetPPIScreen (&ppiScr.x, &ppiScr.y);
866     wxSize page = g_pageSetupData->GetPaperSize();
867     page.x = static_cast<int> (page.x * ppiScr.x / 25.4);
868     page.y = static_cast<int> (page.y * ppiScr.y / 25.4);
869     m_pageRect = wxRect (0,
870                          0,
871                          page.x,
872                          page.y);
873 
874     // get margins informations and convert to printer pixels
875     wxPoint pt = g_pageSetupData->GetMarginTopLeft();
876     int left = pt.x;
877     int top = pt.y;
878     pt = g_pageSetupData->GetMarginBottomRight();
879     int right = pt.x;
880     int bottom = pt.y;
881 
882     top = static_cast<int> (top * ppiScr.y / 25.4);
883     bottom = static_cast<int> (bottom * ppiScr.y / 25.4);
884     left = static_cast<int> (left * ppiScr.x / 25.4);
885     right = static_cast<int> (right * ppiScr.x / 25.4);
886 
887     m_printRect = wxRect (left,
888                           top,
889                           page.x - (left + right),
890                           page.y - (top + bottom));
891 
892     // count pages
893     while (HasPage (*maxPage)) {
894         m_printed = m_edit->FormatRange (0, m_printed, m_edit->GetLength(),
895                                        dc, dc, m_printRect, m_pageRect);
896         *maxPage += 1;
897     }
898     if (*maxPage > 0) *minPage = 1;
899     *selPageFrom = *minPage;
900     *selPageTo = *maxPage;
901 }
902 
HasPage(int WXUNUSED (page))903 bool EditPrint::HasPage (int WXUNUSED(page)) {
904 
905     return (m_printed < m_edit->GetLength());
906 }
907 
PrintScaling(wxDC * dc)908 bool EditPrint::PrintScaling (wxDC *dc){
909 
910     // check for dc, return if none
911     if (!dc) return false;
912 
913     // get printer and screen sizing values
914     wxSize ppiScr;
915     GetPPIScreen (&ppiScr.x, &ppiScr.y);
916     if (ppiScr.x == 0) { // most possible guess 96 dpi
917         ppiScr.x = 96;
918         ppiScr.y = 96;
919     }
920     wxSize ppiPrt;
921     GetPPIPrinter (&ppiPrt.x, &ppiPrt.y);
922     if (ppiPrt.x == 0) { // scaling factor to 1
923         ppiPrt.x = ppiScr.x;
924         ppiPrt.y = ppiScr.y;
925     }
926     wxSize dcSize = dc->GetSize();
927     wxSize pageSize;
928     GetPageSizePixels (&pageSize.x, &pageSize.y);
929 
930     // set user scale
931     float scale_x = (float)(ppiPrt.x * dcSize.x) /
932                     (float)(ppiScr.x * pageSize.x);
933     float scale_y = (float)(ppiPrt.y * dcSize.y) /
934                     (float)(ppiScr.y * pageSize.y);
935     dc->SetUserScale (scale_x, scale_y);
936 
937     return true;
938 }
939 
940 #endif // wxUSE_PRINTING_ARCHITECTURE
941