edit.cpp 32 KB

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