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