PageRenderTime 44ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/Tools/MaterialEditor/wxscintilla_1.69.2/src/ScintillaWX.cpp

https://bitbucket.org/CaptainOz/ogre
C++ | 1179 lines | 922 code | 182 blank | 75 comment | 211 complexity | ccfa3fc7a2718abc029ec4a506952137 MD5 | raw file
Possible License(s): LGPL-2.1, MIT
  1. ////////////////////////////////////////////////////////////////////////////
  2. // Name: ScintillaWX.cxx
  3. // Purpose: A wxWidgets implementation of Scintilla. A class derived
  4. // from ScintillaBase that uses the "wx platform" defined in
  5. // PlatformWX.cxx This class is one end of a bridge between
  6. // the wx world and the Scintilla world. It needs a peer
  7. // object of type wxScintilla to function.
  8. //
  9. // Author: Robin Dunn
  10. //
  11. // Created: 13-Jan-2000
  12. // RCS-ID: $Id: ScintillaWX.cpp,v 1.1 2007/06/08 21:42:37 hudson_b Exp $
  13. // Copyright: (c) 2000 by Total Control Software
  14. // Licence: wxWindows license
  15. /////////////////////////////////////////////////////////////////////////////
  16. #include "ScintillaWX.h"
  17. //?#include "ExternalLexer.h"
  18. #include "PlatWX.h"
  19. #include "wx/wxscintilla.h"
  20. #include <wx/textbuf.h>
  21. #ifdef __WXMSW__
  22. #include <wx/msw/private.h> // GetHwndOf()
  23. #endif
  24. //----------------------------------------------------------------------
  25. // Helper classes
  26. class wxSCITimer : public wxTimer {
  27. public:
  28. wxSCITimer(ScintillaWX* swx) {
  29. this->swx = swx;
  30. }
  31. void Notify() {
  32. swx->DoTick();
  33. }
  34. private:
  35. ScintillaWX* swx;
  36. };
  37. #if wxUSE_DRAG_AND_DROP
  38. class wxStartDragTimer : public wxTimer {
  39. public:
  40. wxStartDragTimer(ScintillaWX* swx) {
  41. this->swx = swx;
  42. }
  43. void Notify() {
  44. swx->DoStartDrag();
  45. }
  46. private:
  47. ScintillaWX* swx;
  48. };
  49. bool wxSCIDropTarget::OnDropText(wxCoord x, wxCoord y, const wxString& data) {
  50. return swx->DoDropText(x, y, data);
  51. }
  52. wxDragResult wxSCIDropTarget::OnEnter(wxCoord x, wxCoord y, wxDragResult def) {
  53. return swx->DoDragEnter(x, y, def);
  54. }
  55. wxDragResult wxSCIDropTarget::OnDragOver(wxCoord x, wxCoord y, wxDragResult def) {
  56. return swx->DoDragOver(x, y, def);
  57. }
  58. void wxSCIDropTarget::OnLeave() {
  59. swx->DoDragLeave();
  60. }
  61. #endif
  62. #if wxUSE_POPUPWIN && wxSCI_USE_POPUP
  63. #include <wx/popupwin.h>
  64. #define wxSCICallTipBase wxPopupWindow
  65. #define param2 wxBORDER_NONE // popup's 2nd param is flags
  66. #else
  67. #define wxSCICallTipBase wxWindow
  68. #define param2 -1 // wxWindow's 2nd param is ID
  69. #endif
  70. #include <wx/dcbuffer.h>
  71. class wxSCICallTip : public wxSCICallTipBase {
  72. public:
  73. wxSCICallTip(wxWindow* parent, CallTip* ct, ScintillaWX* swx)
  74. : wxSCICallTipBase(parent, param2),
  75. m_ct(ct), m_swx(swx), m_cx(-1), m_cy(-1)
  76. {
  77. }
  78. ~wxSCICallTip() {
  79. #if wxUSE_POPUPWIN && wxSCI_USE_POPUP && defined(__WXGTK__)
  80. wxRect rect = GetRect();
  81. rect.x = m_cx;
  82. rect.y = m_cy;
  83. GetParent()->Refresh(false, &rect);
  84. #endif
  85. }
  86. bool AcceptsFocus() const { return false; }
  87. void OnPaint(wxPaintEvent& WXUNUSED(evt)) {
  88. wxBufferedPaintDC dc(this);
  89. Surface* surfaceWindow = Surface::Allocate();
  90. surfaceWindow->Init(&dc, m_ct->wDraw.GetID());
  91. m_ct->PaintCT(surfaceWindow);
  92. surfaceWindow->Release();
  93. delete surfaceWindow;
  94. }
  95. void OnFocus(wxFocusEvent& event) {
  96. GetParent()->SetFocus();
  97. event.Skip();
  98. }
  99. void OnLeftDown(wxMouseEvent& event) {
  100. wxPoint pt = event.GetPosition();
  101. Point p(pt.x, pt.y);
  102. m_ct->MouseClick(p);
  103. m_swx->CallTipClick();
  104. }
  105. #if wxUSE_POPUPWIN && wxSCI_USE_POPUP
  106. virtual void DoSetSize(int x, int y,
  107. int width, int height,
  108. int sizeFlags = wxSIZE_AUTO) {
  109. if (x != -1) {
  110. m_cx = x;
  111. GetParent()->ClientToScreen(&x, NULL);
  112. }
  113. if (y != -1) {
  114. m_cy = y;
  115. GetParent()->ClientToScreen(NULL, &y);
  116. }
  117. wxSCICallTipBase::DoSetSize(x, y, width, height, sizeFlags);
  118. }
  119. #endif
  120. wxPoint GetMyPosition() {
  121. return wxPoint(m_cx, m_cy);
  122. }
  123. private:
  124. CallTip* m_ct;
  125. ScintillaWX* m_swx;
  126. int m_cx, m_cy;
  127. DECLARE_EVENT_TABLE()
  128. };
  129. BEGIN_EVENT_TABLE(wxSCICallTip, wxSCICallTipBase)
  130. EVT_PAINT(wxSCICallTip::OnPaint)
  131. EVT_SET_FOCUS(wxSCICallTip::OnFocus)
  132. EVT_LEFT_DOWN(wxSCICallTip::OnLeftDown)
  133. END_EVENT_TABLE()
  134. //----------------------------------------------------------------------
  135. #if wxUSE_DATAOBJ
  136. static wxTextFileType wxConvertEOLMode(int scintillaMode)
  137. {
  138. wxTextFileType type;
  139. switch (scintillaMode) {
  140. case wxSCI_EOL_CRLF:
  141. type = wxTextFileType_Dos;
  142. break;
  143. case wxSCI_EOL_CR:
  144. type = wxTextFileType_Mac;
  145. break;
  146. case wxSCI_EOL_LF:
  147. type = wxTextFileType_Unix;
  148. break;
  149. default:
  150. type = wxTextBuffer::typeDefault;
  151. break;
  152. }
  153. return type;
  154. }
  155. #endif // wxUSE_DATAOBJ
  156. static int wxCountLines(const char* text, int scintillaMode)
  157. {
  158. char eolchar;
  159. switch (scintillaMode) {
  160. case wxSCI_EOL_CRLF:
  161. case wxSCI_EOL_LF:
  162. eolchar = '\n';
  163. break;
  164. case wxSCI_EOL_CR:
  165. eolchar = '\r';
  166. break;
  167. default:
  168. return 0;
  169. }
  170. int count = 0;
  171. int i = 0;
  172. while (text[i] != 0) {
  173. if (text[i] == eolchar) {
  174. count++;
  175. }
  176. i++;
  177. }
  178. return count;
  179. }
  180. //----------------------------------------------------------------------
  181. // Constructor/Destructor
  182. ScintillaWX::ScintillaWX(wxScintilla* win) {
  183. capturedMouse = false;
  184. focusEvent = false;
  185. wMain = win;
  186. sci = win;
  187. wheelRotation = 0;
  188. Initialise();
  189. #ifdef __WXMSW__
  190. #if wxCHECK_VERSION(2, 5, 0)
  191. sysCaretBitmap = 0;
  192. sysCaretWidth = 0;
  193. sysCaretHeight = 0;
  194. #endif
  195. #endif
  196. #if wxUSE_DRAG_AND_DROP
  197. startDragTimer = new wxStartDragTimer(this);
  198. #endif
  199. }
  200. ScintillaWX::~ScintillaWX() {
  201. #if wxUSE_DRAG_AND_DROP
  202. delete startDragTimer;
  203. #endif
  204. Finalise();
  205. }
  206. //----------------------------------------------------------------------
  207. // base class virtuals
  208. void ScintillaWX::Initialise() {
  209. //ScintillaBase::Initialise();
  210. #if wxUSE_DRAG_AND_DROP
  211. dropTarget = new wxSCIDropTarget;
  212. dropTarget->SetScintilla(this);
  213. sci->SetDropTarget(dropTarget);
  214. dragRectangle = false;
  215. #endif
  216. #ifdef __WXMAC__
  217. vs.extraFontFlag = false; // UseAntiAliasing
  218. #else
  219. vs.extraFontFlag = true; // UseAntiAliasing
  220. #endif
  221. }
  222. void ScintillaWX::Finalise() {
  223. ScintillaBase::Finalise();
  224. SetTicking(false);
  225. SetIdle(false);
  226. DestroySystemCaret();
  227. }
  228. void ScintillaWX::StartDrag() {
  229. #if wxUSE_DRAG_AND_DROP
  230. // We defer the starting of the DnD, otherwise the LeftUp of a normal
  231. // click could be lost and the STC will think it is doing a DnD when the
  232. // user just wanted a normal click.
  233. startDragTimer->Start (200, true);
  234. #endif
  235. }
  236. void ScintillaWX::DoStartDrag() {
  237. #if wxUSE_DRAG_AND_DROP
  238. wxString dragText = sci2wx (drag.s, drag.len);
  239. // Send an event to allow the drag text to be changed
  240. wxScintillaEvent evt(wxEVT_SCI_START_DRAG, sci->GetId());
  241. evt.SetEventObject (sci);
  242. evt.SetDragText (dragText);
  243. evt.SetDragAllowMove (true);
  244. evt.SetPosition (wxMin(sci->GetSelectionStart(), sci->GetSelectionEnd()));
  245. sci->GetEventHandler()->ProcessEvent (evt);
  246. dragText = evt.GetDragText();
  247. dragRectangle = drag.rectangular;
  248. if (dragText.Length()) {
  249. wxDropSource source(sci);
  250. wxTextDataObject data(dragText);
  251. wxDragResult result;
  252. source.SetData(data);
  253. dropWentOutside = true;
  254. result = source.DoDragDrop(evt.GetDragAllowMove());
  255. if (result == wxDragMove && dropWentOutside) ClearSelection();
  256. inDragDrop = false;
  257. SetDragPosition (invalidPosition);
  258. }
  259. #endif
  260. }
  261. bool ScintillaWX::SetIdle(bool on) {
  262. if (idler.state != on) {
  263. // connect or disconnect the EVT_IDLE handler
  264. if (on)
  265. sci->Connect(wxID_ANY, wxEVT_IDLE,
  266. (wxObjectEventFunction) (wxEventFunction) (wxIdleEventFunction) &wxScintilla::OnIdle);
  267. else
  268. sci->Disconnect(wxID_ANY, wxEVT_IDLE,
  269. (wxObjectEventFunction) (wxEventFunction) (wxIdleEventFunction) &wxScintilla::OnIdle);
  270. idler.state = on;
  271. }
  272. return idler.state;
  273. }
  274. void ScintillaWX::SetTicking(bool on) {
  275. wxSCITimer* stiTimer;
  276. if (timer.ticking != on) {
  277. timer.ticking = on;
  278. if (timer.ticking) {
  279. stiTimer = new wxSCITimer(this);
  280. stiTimer->Start(timer.tickSize);
  281. timer.tickerID = stiTimer;
  282. } else {
  283. stiTimer = (wxSCITimer*)timer.tickerID;
  284. stiTimer->Stop();
  285. delete stiTimer;
  286. timer.tickerID = 0;
  287. }
  288. }
  289. timer.ticksToWait = caret.period;
  290. }
  291. void ScintillaWX::SetMouseCapture(bool on) {
  292. if (mouseDownCaptures) {
  293. if (on && !capturedMouse)
  294. sci->CaptureMouse();
  295. else if (!on && capturedMouse && sci->HasCapture())
  296. sci->ReleaseMouse();
  297. capturedMouse = on;
  298. }
  299. }
  300. bool ScintillaWX::HaveMouseCapture() {
  301. return capturedMouse;
  302. }
  303. void ScintillaWX::ScrollText(int linesToMove) {
  304. int dy = vs.lineHeight * (linesToMove);
  305. sci->ScrollWindow(0, dy);
  306. sci->Update();
  307. }
  308. void ScintillaWX::SetVerticalScrollPos() {
  309. if (sci->m_vScrollBar == NULL) { // Use built-in scrollbar
  310. sci->SetScrollPos(wxVERTICAL, topLine);
  311. }
  312. else { // otherwise use the one that's been given to us
  313. sci->m_vScrollBar->SetThumbPosition(topLine);
  314. }
  315. }
  316. void ScintillaWX::SetHorizontalScrollPos() {
  317. if (sci->m_hScrollBar == NULL) { // Use built-in scrollbar
  318. sci->SetScrollPos(wxHORIZONTAL, xOffset);
  319. }
  320. else { // otherwise use the one that's been given to us
  321. sci->m_hScrollBar->SetThumbPosition(xOffset);
  322. }
  323. }
  324. const int H_SCROLL_STEP = 20;
  325. bool ScintillaWX::ModifyScrollBars(int nMax, int nPage) {
  326. bool modified = false;
  327. int vertEnd = nMax;
  328. if (!verticalScrollBarVisible)
  329. vertEnd = 0;
  330. // Check the vertical scrollbar
  331. if (sci->m_vScrollBar == NULL) { // Use built-in scrollbar
  332. int sbMax = sci->GetScrollRange(wxVERTICAL);
  333. int sbThumb = sci->GetScrollThumb(wxVERTICAL);
  334. int sbPos = sci->GetScrollPos(wxVERTICAL);
  335. if (sbMax != vertEnd || sbThumb != nPage) {
  336. sci->SetScrollbar(wxVERTICAL, sbPos, nPage, vertEnd+1);
  337. modified = true;
  338. }
  339. }
  340. else { // otherwise use the one that's been given to us
  341. int sbMax = sci->m_vScrollBar->GetRange();
  342. int sbPage = sci->m_vScrollBar->GetPageSize();
  343. int sbPos = sci->m_vScrollBar->GetThumbPosition();
  344. if (sbMax != vertEnd || sbPage != nPage) {
  345. sci->m_vScrollBar->SetScrollbar(sbPos, nPage, vertEnd+1, nPage);
  346. modified = true;
  347. }
  348. }
  349. // Check the horizontal scrollbar
  350. PRectangle rcText = GetTextRectangle();
  351. int horizEnd = scrollWidth;
  352. if (horizEnd < 0)
  353. horizEnd = 0;
  354. if (!horizontalScrollBarVisible || (wrapState != eWrapNone))
  355. horizEnd = 0;
  356. int pageWidth = rcText.Width();
  357. if (sci->m_hScrollBar == NULL) { // Use built-in scrollbar
  358. int sbMax = sci->GetScrollRange(wxHORIZONTAL);
  359. int sbThumb = sci->GetScrollThumb(wxHORIZONTAL);
  360. int sbPos = sci->GetScrollPos(wxHORIZONTAL);
  361. if ((sbMax != horizEnd) || (sbThumb != pageWidth) || (sbPos != 0)) {
  362. sci->SetScrollbar(wxHORIZONTAL, sbPos, pageWidth, horizEnd);
  363. modified = true;
  364. if (scrollWidth < pageWidth) {
  365. HorizontalScrollTo(0);
  366. }
  367. }
  368. }
  369. else { // otherwise use the one that's been given to us
  370. int sbMax = sci->m_hScrollBar->GetRange();
  371. int sbThumb = sci->m_hScrollBar->GetPageSize();
  372. int sbPos = sci->m_hScrollBar->GetThumbPosition();
  373. if ((sbMax != horizEnd) || (sbThumb != pageWidth) || (sbPos != 0)) {
  374. sci->m_hScrollBar->SetScrollbar(sbPos, pageWidth, horizEnd, pageWidth);
  375. modified = true;
  376. if (scrollWidth < pageWidth) {
  377. HorizontalScrollTo(0);
  378. }
  379. }
  380. }
  381. return modified;
  382. }
  383. void ScintillaWX::NotifyChange() {
  384. sci->NotifyChange();
  385. }
  386. void ScintillaWX::NotifyParent(SCNotification scn) {
  387. sci->NotifyParent(&scn);
  388. }
  389. // This method is overloaded from ScintillaBase in order to prevent the
  390. // AutoComplete window from being destroyed when it gets the focus. There is
  391. // a side effect that the AutoComp will also not be destroyed when switching
  392. // to another window, but I think that is okay.
  393. void ScintillaWX::CancelModes() {
  394. if (! focusEvent)
  395. AutoCompleteCancel();
  396. ct.CallTipCancel();
  397. Editor::CancelModes();
  398. }
  399. void ScintillaWX::Copy() {
  400. if (currentPos != anchor) {
  401. SelectionText st;
  402. CopySelectionRange(&st);
  403. CopyToClipboard(st);
  404. }
  405. }
  406. void ScintillaWX::Paste() {
  407. pdoc->BeginUndoAction();
  408. ClearSelection();
  409. #if wxUSE_DATAOBJ
  410. wxTextDataObject data;
  411. wxString textString;
  412. wxWX2MBbuf buf;
  413. int len = 0;
  414. bool rectangular = false;
  415. if (wxTheClipboard->Open()) {
  416. wxTheClipboard->UsePrimarySelection(false);
  417. wxCustomDataObject selData(wxDF_PRIVATE);
  418. bool gotRectData = wxTheClipboard->GetData(selData);
  419. if (gotRectData && selData.GetSize()>1) {
  420. const char* rectBuf = (const char*)selData.GetData();
  421. rectangular = rectBuf[0] == (char)1;
  422. len = selData.GetDataSize()-1;
  423. char* buffer = new char[len];
  424. memcpy (buffer, rectBuf+1, len);
  425. textString = sci2wx(buffer, len);
  426. delete buffer;
  427. } else {
  428. bool gotData = wxTheClipboard->GetData(data);
  429. if (gotData) {
  430. textString = wxTextBuffer::Translate (data.GetText(),
  431. wxConvertEOLMode(pdoc->eolMode));
  432. }
  433. }
  434. data.SetText(wxEmptyString); // free the data object content
  435. wxTheClipboard->Close();
  436. }
  437. buf = (wxWX2MBbuf)wx2sci(textString);
  438. len = strlen(buf);
  439. int newPos = 0;
  440. if (rectangular) {
  441. int newLine = pdoc->LineFromPosition (currentPos) + wxCountLines (buf, pdoc->eolMode);
  442. int newCol = pdoc->GetColumn(currentPos);
  443. PasteRectangular (currentPos, buf, len);
  444. newPos = pdoc->FindColumn (newLine, newCol);
  445. } else {
  446. pdoc->InsertString (currentPos, buf, len);
  447. newPos = currentPos + len;
  448. }
  449. SetEmptySelection (newPos);
  450. #endif // wxUSE_DATAOBJ
  451. pdoc->EndUndoAction();
  452. NotifyChange();
  453. Redraw();
  454. }
  455. void ScintillaWX::CopyToClipboard (const SelectionText& st) {
  456. #if wxUSE_CLIPBOARD
  457. if (wxTheClipboard->Open()) {
  458. wxTheClipboard->UsePrimarySelection (false);
  459. wxString text = wxTextBuffer::Translate (sci2wx(st.s, st.len-1));
  460. // composite object will hold "plain text" for pasting in other programs and a custom
  461. // object for local use that remembers what kind of selection was made (stream or
  462. // rectangular).
  463. wxDataObjectComposite* obj = new wxDataObjectComposite();
  464. wxCustomDataObject* rectData = new wxCustomDataObject (wxDF_PRIVATE);
  465. char* buffer = new char[st.len+1];
  466. buffer[0] = (st.rectangular)? (char)1 : (char)0;
  467. memcpy (buffer+1, st.s, st.len);
  468. rectData->SetData (st.len+1, buffer);
  469. delete buffer;
  470. obj->Add (rectData, true);
  471. obj->Add (new wxTextDataObject (text));
  472. wxTheClipboard->SetData (obj);
  473. wxTheClipboard->Close();
  474. }
  475. #else
  476. wxUnusedVar(st);
  477. #endif // wxUSE_CLIPBOARD
  478. }
  479. bool ScintillaWX::CanPaste() {
  480. #if wxUSE_CLIPBOARD
  481. bool canPaste = false;
  482. bool didOpen;
  483. if (Editor::CanPaste()) {
  484. didOpen = !wxTheClipboard->IsOpened();
  485. if ( didOpen )
  486. wxTheClipboard->Open();
  487. if (wxTheClipboard->IsOpened()) {
  488. wxTheClipboard->UsePrimarySelection(false);
  489. canPaste = wxTheClipboard->IsSupported(wxUSE_UNICODE ? wxDF_UNICODETEXT : wxDF_TEXT);
  490. if (didOpen)
  491. wxTheClipboard->Close();
  492. }
  493. }
  494. return canPaste;
  495. #else
  496. return false;
  497. #endif // wxUSE_CLIPBOARD
  498. }
  499. void ScintillaWX::CreateCallTipWindow(PRectangle) {
  500. if (! ct.wCallTip.Created() ) {
  501. ct.wCallTip = new wxSCICallTip(sci, &ct, this);
  502. ct.wDraw = ct.wCallTip;
  503. }
  504. }
  505. void ScintillaWX::AddToPopUp(const char *label, int cmd, bool enabled) {
  506. if (!label[0])
  507. ((wxMenu*)popup.GetID())->AppendSeparator();
  508. else
  509. ((wxMenu*)popup.GetID())->Append(cmd, wxGetTranslation(sci2wx(label)));
  510. if (!enabled)
  511. ((wxMenu*)popup.GetID())->Enable(cmd, enabled);
  512. }
  513. // This is called by the Editor base class whenever something is selected
  514. void ScintillaWX::ClaimSelection() {
  515. #if 0
  516. // Until wxGTK is able to support using both the primary selection and the
  517. // clipboard at the same time I think it causes more problems than it is
  518. // worth to implement this method. Selecting text should not clear the
  519. // clipboard. --Robin
  520. #ifdef __WXGTK__
  521. // Put the selected text in the PRIMARY selection
  522. if (currentPos != anchor) {
  523. SelectionText st;
  524. CopySelectionRange(&st);
  525. if (wxTheClipboard->Open()) {
  526. wxTheClipboard->UsePrimarySelection(true);
  527. wxString text = sci2wx(st.s, st.len);
  528. wxTheClipboard->SetData(new wxTextDataObject(text));
  529. wxTheClipboard->UsePrimarySelection(false);
  530. wxTheClipboard->Close();
  531. }
  532. }
  533. #endif
  534. #endif
  535. }
  536. void ScintillaWX::UpdateSystemCaret() {
  537. #ifdef __WXMSW__
  538. if (hasFocus) {
  539. if (HasCaretSizeChanged()) {
  540. DestroySystemCaret();
  541. CreateSystemCaret();
  542. }
  543. Point pos = LocationFromPosition(currentPos);
  544. #if wxCHECK_VERSION(2, 5, 0)
  545. ::SetCaretPos(pos.x, pos.y);
  546. #endif
  547. }
  548. #endif
  549. }
  550. bool ScintillaWX::HasCaretSizeChanged() {
  551. #ifdef __WXMSW__
  552. #if !wxCHECK_VERSION(2, 5, 0)
  553. return false;
  554. #else
  555. if (( (0 != vs.caretWidth) && (sysCaretWidth != vs.caretWidth) )
  556. || (0 != vs.lineHeight) && (sysCaretHeight != vs.lineHeight)) {
  557. return true;
  558. }
  559. #endif
  560. #endif
  561. return false;
  562. }
  563. bool ScintillaWX::CreateSystemCaret() {
  564. #ifdef __WXMSW__
  565. #if !wxCHECK_VERSION(2, 5, 0)
  566. return false;
  567. #else
  568. sysCaretWidth = vs.caretWidth;
  569. if (0 == sysCaretWidth) {
  570. sysCaretWidth = 1;
  571. }
  572. sysCaretHeight = vs.lineHeight;
  573. int bitmapSize = (((sysCaretWidth + 15) & ~15) >> 3) * sysCaretHeight;
  574. char *bits = new char[bitmapSize];
  575. memset(bits, 0, bitmapSize);
  576. sysCaretBitmap = ::CreateBitmap(sysCaretWidth, sysCaretHeight, 1,
  577. 1, reinterpret_cast<BYTE *>(bits));
  578. delete [] bits;
  579. BOOL retval = ::CreateCaret(GetHwndOf(sci), sysCaretBitmap,
  580. sysCaretWidth, sysCaretHeight);
  581. ::ShowCaret(GetHwndOf(sci));
  582. return retval != 0;
  583. #endif
  584. #else
  585. return false;
  586. #endif
  587. }
  588. bool ScintillaWX::DestroySystemCaret() {
  589. #ifdef __WXMSW__
  590. #if !wxCHECK_VERSION(2, 5, 0)
  591. return false;
  592. #else
  593. ::HideCaret(GetHwndOf(sci));
  594. BOOL retval = ::DestroyCaret();
  595. if (sysCaretBitmap) {
  596. ::DeleteObject(sysCaretBitmap);
  597. sysCaretBitmap = 0;
  598. }
  599. return retval != 0;
  600. #endif
  601. #else
  602. return false;
  603. #endif
  604. }
  605. //----------------------------------------------------------------------
  606. long ScintillaWX::DefWndProc(unsigned int /*iMessage*/, unsigned long /*wParam*/, long /*lParam*/) {
  607. return 0;
  608. }
  609. long ScintillaWX::WndProc(unsigned int iMessage, unsigned long wParam, long lParam) {
  610. switch (iMessage) {
  611. case SCI_CALLTIPSHOW: {
  612. // NOTE: This is copied here from scintilla/src/ScintillaBase.cxx
  613. // because of the little tweak that needs done below for wxGTK.
  614. // When updating new versions double check that this is still
  615. // needed, and that any new code there is copied here too.
  616. Point pt = LocationFromPosition(wParam);
  617. char* defn = reinterpret_cast<char *>(lParam);
  618. AutoCompleteCancel();
  619. pt.y += vs.lineHeight;
  620. PRectangle rc = ct.CallTipStart(currentPos, pt,
  621. defn,
  622. vs.styles[STYLE_DEFAULT].fontName,
  623. vs.styles[STYLE_DEFAULT].sizeZoomed,
  624. CodePage(),
  625. vs.styles[STYLE_DEFAULT].characterSet,
  626. wMain);
  627. // If the call-tip window would be out of the client
  628. // space, adjust so it displays above the text.
  629. PRectangle rcClient = GetClientRectangle();
  630. if (rc.bottom > rcClient.bottom) {
  631. #ifdef __WXGTK__
  632. int offset = int(vs.lineHeight * 1.25) + rc.Height();
  633. #else
  634. int offset = vs.lineHeight + rc.Height();
  635. #endif
  636. rc.top -= offset;
  637. rc.bottom -= offset;
  638. }
  639. // Now display the window.
  640. CreateCallTipWindow(rc);
  641. ct.wCallTip.SetPositionRelative(rc, wMain);
  642. ct.wCallTip.Show();
  643. break;
  644. }
  645. /*? TODO
  646. #ifdef SCI_LEXER
  647. case SCI_LOADLEXERLIBRARY:
  648. LexerManager::GetInstance()->Load((const char*)lParam);
  649. break;
  650. #endif ?*/
  651. default:
  652. return ScintillaBase::WndProc(iMessage, wParam, lParam);
  653. }
  654. return 0;
  655. }
  656. //----------------------------------------------------------------------
  657. // Event delegates
  658. void ScintillaWX::DoPaint(wxDC* dc, wxRect rect) {
  659. paintState = painting;
  660. Surface* surfaceWindow = Surface::Allocate();
  661. surfaceWindow->Init(dc, wMain.GetID());
  662. rcPaint = PRectangleFromwxRect(rect);
  663. PRectangle rcClient = GetClientRectangle();
  664. paintingAllText = rcPaint.Contains(rcClient);
  665. ClipChildren(*dc, rcPaint);
  666. Paint(surfaceWindow, rcPaint);
  667. delete surfaceWindow;
  668. if (paintState == paintAbandoned) {
  669. // Painting area was insufficient to cover new styling or brace
  670. // highlight positions
  671. FullPaint();
  672. }
  673. paintState = notPainting;
  674. }
  675. void ScintillaWX::DoHScroll(int type, int pos) {
  676. int xPos = xOffset;
  677. PRectangle rcText = GetTextRectangle();
  678. int pageWidth = rcText.Width() * 2 / 3;
  679. if (type == wxEVT_SCROLLWIN_LINEUP || type == wxEVT_SCROLL_LINEUP)
  680. xPos -= H_SCROLL_STEP;
  681. else if (type == wxEVT_SCROLLWIN_LINEDOWN || type == wxEVT_SCROLL_LINEDOWN)
  682. xPos += H_SCROLL_STEP;
  683. else if (type == wxEVT_SCROLLWIN_PAGEUP || type == wxEVT_SCROLL_PAGEUP)
  684. xPos -= pageWidth;
  685. else if (type == wxEVT_SCROLLWIN_PAGEDOWN || type == wxEVT_SCROLL_PAGEDOWN) {
  686. xPos += pageWidth;
  687. if (xPos > scrollWidth - rcText.Width()) {
  688. xPos = scrollWidth - rcText.Width();
  689. }
  690. }
  691. else if (type == wxEVT_SCROLLWIN_TOP || type == wxEVT_SCROLL_TOP)
  692. xPos = 0;
  693. else if (type == wxEVT_SCROLLWIN_BOTTOM || type == wxEVT_SCROLL_BOTTOM)
  694. xPos = scrollWidth;
  695. else if (type == wxEVT_SCROLLWIN_THUMBTRACK || type == wxEVT_SCROLL_THUMBTRACK)
  696. xPos = pos;
  697. HorizontalScrollTo(xPos);
  698. }
  699. void ScintillaWX::DoVScroll(int type, int pos) {
  700. int topLineNew = topLine;
  701. if (type == wxEVT_SCROLLWIN_LINEUP || type == wxEVT_SCROLL_LINEUP)
  702. topLineNew -= 1;
  703. else if (type == wxEVT_SCROLLWIN_LINEDOWN || type == wxEVT_SCROLL_LINEDOWN)
  704. topLineNew += 1;
  705. else if (type == wxEVT_SCROLLWIN_PAGEUP || type == wxEVT_SCROLL_PAGEUP)
  706. topLineNew -= LinesToScroll();
  707. else if (type == wxEVT_SCROLLWIN_PAGEDOWN || type == wxEVT_SCROLL_PAGEDOWN)
  708. topLineNew += LinesToScroll();
  709. else if (type == wxEVT_SCROLLWIN_TOP || type == wxEVT_SCROLL_TOP)
  710. topLineNew = 0;
  711. else if (type == wxEVT_SCROLLWIN_BOTTOM || type == wxEVT_SCROLL_BOTTOM)
  712. topLineNew = MaxScrollPos();
  713. else if (type == wxEVT_SCROLLWIN_THUMBTRACK || type == wxEVT_SCROLL_THUMBTRACK)
  714. topLineNew = pos;
  715. ScrollTo(topLineNew);
  716. }
  717. void ScintillaWX::DoMouseWheel(int rotation, int delta,
  718. int linesPerAction, int ctrlDown,
  719. bool isPageScroll ) {
  720. int topLineNew = topLine;
  721. int lines;
  722. if (ctrlDown) { // Zoom the fonts if Ctrl key down
  723. if (rotation < 0) {
  724. KeyCommand(SCI_ZOOMIN);
  725. }
  726. else {
  727. KeyCommand(SCI_ZOOMOUT);
  728. }
  729. }
  730. else { // otherwise just scroll the window
  731. if ( !delta )
  732. delta = 120;
  733. wheelRotation += rotation;
  734. lines = wheelRotation / delta;
  735. wheelRotation -= lines * delta;
  736. if (lines != 0) {
  737. if (isPageScroll)
  738. lines = lines * LinesOnScreen(); // lines is either +1 or -1
  739. else
  740. lines *= linesPerAction;
  741. topLineNew -= lines;
  742. ScrollTo(topLineNew);
  743. }
  744. }
  745. }
  746. void ScintillaWX::DoSize(int WXUNUSED(width), int WXUNUSED(height)) {
  747. ChangeSize();
  748. }
  749. void ScintillaWX::DoLoseFocus(){
  750. focusEvent = true;
  751. SetFocusState(false);
  752. focusEvent = false;
  753. DestroySystemCaret();
  754. }
  755. void ScintillaWX::DoGainFocus(){
  756. focusEvent = true;
  757. SetFocusState(true);
  758. focusEvent = false;
  759. DestroySystemCaret();
  760. CreateSystemCaret();
  761. }
  762. void ScintillaWX::DoSysColourChange() {
  763. InvalidateStyleData();
  764. }
  765. void ScintillaWX::DoLeftButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt) {
  766. ButtonDown(pt, curTime, shift, ctrl, alt);
  767. }
  768. void ScintillaWX::DoLeftButtonUp(Point pt, unsigned int curTime, bool ctrl) {
  769. ButtonUp(pt, curTime, ctrl);
  770. #if wxUSE_DRAG_AND_DROP
  771. if (startDragTimer->IsRunning()) {
  772. startDragTimer->Stop();
  773. SetDragPosition(invalidPosition);
  774. SetEmptySelection(PositionFromLocation(pt));
  775. ShowCaretAtCurrentPosition();
  776. }
  777. #endif
  778. }
  779. void ScintillaWX::DoLeftButtonMove(Point pt) {
  780. ButtonMove(pt);
  781. }
  782. #ifdef __WXGTK__
  783. void ScintillaWX::DoMiddleButtonUp(Point pt) {
  784. // Set the current position to the mouse click point and
  785. // then paste in the PRIMARY selection, if any. wxGTK only.
  786. int newPos = PositionFromLocation(pt);
  787. MovePositionTo(newPos, noSel, true);
  788. pdoc->BeginUndoAction();
  789. wxTextDataObject data;
  790. bool gotData = false;
  791. if (wxTheClipboard->Open()) {
  792. wxTheClipboard->UsePrimarySelection(true);
  793. gotData = wxTheClipboard->GetData(data);
  794. wxTheClipboard->UsePrimarySelection(false);
  795. wxTheClipboard->Close();
  796. }
  797. if (gotData) {
  798. wxString text = wxTextBuffer::Translate (data.GetText(),
  799. wxConvertEOLMode(pdoc->eolMode));
  800. data.SetText(wxEmptyString); // free the data object content
  801. wxWX2MBbuf buf = (wxWX2MBbuf)wx2sci(text);
  802. //? text = wxEmptyString; // free text
  803. int len = strlen(buf);
  804. pdoc->InsertString(currentPos, buf, len);
  805. SetEmptySelection(currentPos + len);
  806. }
  807. pdoc->EndUndoAction();
  808. NotifyChange();
  809. Redraw();
  810. ShowCaretAtCurrentPosition();
  811. EnsureCaretVisible();
  812. }
  813. #else
  814. void ScintillaWX::DoMiddleButtonUp(Point WXUNUSED(pt)) {
  815. }
  816. #endif
  817. void ScintillaWX::DoAddChar(int key) {
  818. #if wxUSE_UNICODE
  819. wxChar wszChars[2];
  820. wszChars[0] = (wxChar)key;
  821. wszChars[1] = 0;
  822. wxWX2MBbuf buf = (wxWX2MBbuf)wx2sci(wszChars);
  823. AddCharUTF((char*)buf.data(), strlen(buf));
  824. #else
  825. AddChar((char)key);
  826. #endif
  827. }
  828. int ScintillaWX::DoKeyDown(const wxKeyEvent& evt, bool* consumed)
  829. {
  830. int key = evt.GetKeyCode();
  831. bool shift = evt.ShiftDown(),
  832. ctrl = evt.ControlDown(),
  833. alt = evt.AltDown();
  834. if (ctrl && key >= 1 && key <= 26 && key != WXK_BACK)
  835. key += 'A' - 1;
  836. switch (key) {
  837. case WXK_DOWN: key = SCK_DOWN; break;
  838. case WXK_UP: key = SCK_UP; break;
  839. case WXK_LEFT: key = SCK_LEFT; break;
  840. case WXK_RIGHT: key = SCK_RIGHT; break;
  841. case WXK_HOME: key = SCK_HOME; break;
  842. case WXK_END: key = SCK_END; break;
  843. #if !wxCHECK_VERSION(2, 7, 0)
  844. case WXK_PAGEUP: // fall through
  845. #endif
  846. case WXK_PRIOR: key = SCK_PRIOR; break;
  847. #if !wxCHECK_VERSION(2, 7, 0)
  848. case WXK_PAGEDOWN: // fall through
  849. #endif
  850. case WXK_NEXT: key = SCK_NEXT; break;
  851. case WXK_DELETE: key = SCK_DELETE; break;
  852. case WXK_INSERT: key = SCK_INSERT; break;
  853. case WXK_ESCAPE: key = SCK_ESCAPE; break;
  854. case WXK_BACK: key = SCK_BACK; break;
  855. case WXK_TAB: key = SCK_TAB; break;
  856. case WXK_NUMPAD_ENTER: // fall through
  857. case WXK_RETURN: key = SCK_RETURN; break;
  858. case WXK_ADD: // fall through
  859. case WXK_NUMPAD_ADD: key = SCK_ADD; break;
  860. case WXK_SUBTRACT: // fall through
  861. case WXK_NUMPAD_SUBTRACT: key = SCK_SUBTRACT; break;
  862. case WXK_DIVIDE: // fall through
  863. case WXK_NUMPAD_DIVIDE: key = SCK_DIVIDE; break;
  864. case WXK_CONTROL: key = 0; break;
  865. case WXK_ALT: key = 0; break;
  866. case WXK_SHIFT: key = 0; break;
  867. case WXK_MENU: key = 0; break;
  868. }
  869. #ifdef __WXMAC__
  870. if ( evt.MetaDown() ) {
  871. // check for a few common Mac Meta-key combos and remap them to Ctrl
  872. // for Scintilla
  873. switch ( key ) {
  874. case 'Z': // Undo
  875. case 'X': // Cut
  876. case 'C': // Copy
  877. case 'V': // Paste
  878. case 'A': // Select All
  879. ctrl = true;
  880. break;
  881. }
  882. }
  883. #endif
  884. int rv = KeyDown(key, shift, ctrl, alt, consumed);
  885. if (key)
  886. return rv;
  887. else
  888. return 1;
  889. }
  890. void ScintillaWX::DoCommand(int ID) {
  891. Command(ID);
  892. }
  893. void ScintillaWX::DoContextMenu(Point pt) {
  894. if (displayPopupMenu)
  895. ContextMenu(pt);
  896. }
  897. void ScintillaWX::DoOnListBox() {
  898. AutoCompleteCompleted();
  899. }
  900. void ScintillaWX::DoOnIdle(wxIdleEvent& evt) {
  901. if ( Idle() )
  902. evt.RequestMore();
  903. else
  904. SetIdle(false);
  905. }
  906. //----------------------------------------------------------------------
  907. #if wxUSE_DRAG_AND_DROP
  908. bool ScintillaWX::DoDropText(long x, long y, const wxString& data) {
  909. SetDragPosition(invalidPosition);
  910. wxString text = wxTextBuffer::Translate (data, wxConvertEOLMode(pdoc->eolMode));
  911. // Send an event to allow the drag details to be changed
  912. wxScintillaEvent evt(wxEVT_SCI_DO_DROP, sci->GetId());
  913. evt.SetEventObject(sci);
  914. evt.SetDragResult(dragResult);
  915. evt.SetX(x);
  916. evt.SetY(y);
  917. evt.SetPosition(PositionFromLocation(Point(x,y)));
  918. evt.SetDragText(text);
  919. sci->GetEventHandler()->ProcessEvent(evt);
  920. dragResult = evt.GetDragResult();
  921. if (dragResult == wxDragMove || dragResult == wxDragCopy) {
  922. DropAt(evt.GetPosition(),
  923. wx2sci(evt.GetDragText()),
  924. dragResult == wxDragMove,
  925. dragRectangle);
  926. return true;
  927. }
  928. return false;
  929. }
  930. wxDragResult ScintillaWX::DoDragEnter(wxCoord WXUNUSED(x), wxCoord WXUNUSED(y), wxDragResult def) {
  931. dragResult = def;
  932. return dragResult;
  933. }
  934. wxDragResult ScintillaWX::DoDragOver(wxCoord x, wxCoord y, wxDragResult def) {
  935. SetDragPosition(PositionFromLocation(Point(x, y)));
  936. // Send an event to allow the drag result to be changed
  937. wxScintillaEvent evt(wxEVT_SCI_DRAG_OVER, sci->GetId());
  938. evt.SetEventObject(sci);
  939. evt.SetDragResult(def);
  940. evt.SetX(x);
  941. evt.SetY(y);
  942. evt.SetPosition(PositionFromLocation(Point(x,y)));
  943. sci->GetEventHandler()->ProcessEvent(evt);
  944. dragResult = evt.GetDragResult();
  945. return dragResult;
  946. }
  947. void ScintillaWX::DoDragLeave() {
  948. SetDragPosition(invalidPosition);
  949. }
  950. #endif
  951. //----------------------------------------------------------------------
  952. // Force the whole window to be repainted
  953. void ScintillaWX::FullPaint() {
  954. #ifndef __WXMAC__
  955. sci->Refresh(false);
  956. #endif
  957. sci->Update();
  958. }
  959. void ScintillaWX::DoScrollToLine(int line) {
  960. ScrollTo(line);
  961. }
  962. void ScintillaWX::DoScrollToColumn(int column) {
  963. HorizontalScrollTo(column * vs.spaceWidth);
  964. }
  965. #ifdef __WXGTK__
  966. void ScintillaWX::ClipChildren(wxDC& dc, PRectangle rect) {
  967. // wxGTK > 2.5 doesn't appear to need this explicit clipping code any longer
  968. #if !wxCHECK_VERSION(2, 5, 0)
  969. wxRegion rgn(wxRectFromPRectangle(rect));
  970. if (ac.Active()) {
  971. wxRect childRect = ((wxWindow*)ac.lb->GetID())->GetRect();
  972. rgn.Subtract(childRect);
  973. }
  974. if (ct.inCallTipMode) {
  975. wxSCICallTip* tip = (wxSCICallTip*)ct.wCallTip.GetID();
  976. wxRect childRect = tip->GetRect();
  977. #if wxUSE_POPUPWIN && wxSCI_USE_POPUP
  978. childRect.SetPosition(tip->GetMyPosition());
  979. #endif
  980. rgn.Subtract(childRect);
  981. }
  982. dc.SetClippingRegion(rgn);
  983. #endif
  984. }
  985. #else
  986. void ScintillaWX::ClipChildren(wxDC& WXUNUSED(dc), PRectangle WXUNUSED(rect)) {
  987. }
  988. #endif
  989. void ScintillaWX::SetUseAntiAliasing(bool useAA) {
  990. vs.extraFontFlag = useAA;
  991. InvalidateStyleRedraw();
  992. }
  993. bool ScintillaWX::GetUseAntiAliasing() {
  994. return vs.extraFontFlag;
  995. }
  996. //----------------------------------------------------------------------
  997. //----------------------------------------------------------------------