aboutsummaryrefslogtreecommitdiffhomepage
path: root/qt/ScintillaEditBase/ScintillaQt.cpp
diff options
context:
space:
mode:
authornyamatongwe <unknown>2012-05-17 12:46:29 +1000
committernyamatongwe <unknown>2012-05-17 12:46:29 +1000
commitbf8b35542c4be4b8eebb71ca2ad518da2e12b850 (patch)
treeeab094df23f84c33c7ed03f3412a63a060d31eac /qt/ScintillaEditBase/ScintillaQt.cpp
parent29c92749f25f24795ecd9fec2b6705129ebbd654 (diff)
downloadscintilla-mirror-bf8b35542c4be4b8eebb71ca2ad518da2e12b850.tar.gz
Qt platform layer added. Based on an implementation from Jason Haslam
at Scientific Toolworks, Inc. with additions performed for Wingware.
Diffstat (limited to 'qt/ScintillaEditBase/ScintillaQt.cpp')
-rw-r--r--qt/ScintillaEditBase/ScintillaQt.cpp772
1 files changed, 772 insertions, 0 deletions
diff --git a/qt/ScintillaEditBase/ScintillaQt.cpp b/qt/ScintillaEditBase/ScintillaQt.cpp
new file mode 100644
index 000000000..e65390f4a
--- /dev/null
+++ b/qt/ScintillaEditBase/ScintillaQt.cpp
@@ -0,0 +1,772 @@
+//
+// Copyright (c) 1990-2011, Scientific Toolworks, Inc.
+//
+// The License.txt file describes the conditions under which this software may be distributed.
+//
+// Author: Jason Haslam
+//
+// Additions Copyright (c) 2011 Archaeopteryx Software, Inc. d/b/a Wingware
+// ScintillaQt.cpp - Qt specific subclass of ScintillaBase
+
+#include "PlatQt.h"
+#include "ScintillaQt.h"
+#ifdef SCI_LEXER
+#include "LexerModule.h"
+#include "ExternalLexer.h"
+#endif
+
+#include <QApplication>
+#include <QDrag>
+#include <QInputContext>
+#include <QMimeData>
+#include <QMenu>
+#include <QScrollBar>
+#include <QTimer>
+#include <QTextCodec>
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+
+ScintillaQt::ScintillaQt(QAbstractScrollArea *parent)
+: QObject(parent), scrollArea(parent), vMax(0), hMax(0), vPage(0), hPage(0),
+ haveMouseCapture(false), dragWasDropped(false)
+{
+
+ wMain = scrollArea->viewport();
+
+ // On OS X drawing text into a pixmap moves it around 1 pixel to
+ // the right compared to drawing it directly onto a window.
+ // Buffered drawing turned off by default to avoid this.
+ WndProc(SCI_SETBUFFEREDDRAW, false, 0);
+
+ Initialise();
+}
+
+ScintillaQt::~ScintillaQt()
+{
+ SetTicking(false);
+}
+
+void ScintillaQt::tick()
+{
+ Tick();
+}
+
+void ScintillaQt::execCommand(QAction *action)
+{
+ int command = action->data().toInt();
+ Command(command);
+}
+
+#if defined(Q_OS_WIN)
+static const QString sMSDEVColumnSelect("MSDEVColumnSelect");
+static const QString sWrappedMSDEVColumnSelect("application/x-qt-windows-mime;value=\"MSDEVColumnSelect\"");
+#elif defined(Q_OS_MAC)
+static const QString sScintillaRecPboardType("com.scintilla.utf16-plain-text.rectangular");
+static const QString sScintillaRecMimeType("text/x-scintilla.utf16-plain-text.rectangular");
+#else
+// Linux
+static const QString sMimeRectangularMarker("text/x-rectangular-marker");
+#endif
+
+#ifdef Q_OS_MAC
+
+class ScintillaRectangularMime : public QMacPasteboardMime {
+public:
+ ScintillaRectangularMime() : QMacPasteboardMime(MIME_ALL) {
+ }
+
+ QString convertorName() {
+ return QString("ScintillaRectangularMime");
+ }
+
+ bool canConvert(const QString &mime, QString flav) {
+ return mimeFor(flav) == mime;
+ }
+
+ QString mimeFor(QString flav) {
+ if (flav == sScintillaRecPboardType)
+ return sScintillaRecMimeType;
+ return QString();
+ }
+
+ QString flavorFor(const QString &mime) {
+ if (mime == sScintillaRecMimeType)
+ return sScintillaRecPboardType;
+ return QString();
+ }
+
+ QVariant convertToMime(const QString & /* mime */, QList<QByteArray> data, QString /* flav */) {
+ QByteArray all;
+ foreach (QByteArray i, data) {
+ all += i;
+ }
+ return QVariant(all);
+ }
+
+ QList<QByteArray> convertFromMime(const QString & /* mime */, QVariant data, QString /* flav */) {
+ QByteArray a = data.toByteArray();
+ QList<QByteArray> l;
+ l.append(a);
+ return l;
+ }
+
+};
+
+// The Mime object registers itself but only want one for all Scintilla instances.
+// Should delete at exit to help memory leak detection but that would be extra work
+// and, since the clipboard exists after last Scintilla instance, may be complex.
+static ScintillaRectangularMime *singletonMime = 0;
+
+#endif
+
+void ScintillaQt::Initialise()
+{
+#if defined(Q_OS_WIN) || defined(Q_OS_MAC)
+ rectangularSelectionModifier = SCMOD_ALT;
+#else
+ rectangularSelectionModifier = SCMOD_CTRL;
+#endif
+
+#ifdef Q_OS_MAC
+ if (!singletonMime) {
+ singletonMime = new ScintillaRectangularMime();
+
+ QStringList slTypes(sScintillaRecPboardType);
+ qRegisterDraggedTypes(slTypes);
+ }
+#endif
+
+ connect(QApplication::clipboard(), SIGNAL(selectionChanged()),
+ this, SLOT(SelectionChanged()));
+}
+
+void ScintillaQt::Finalise()
+{
+ SetTicking(false);
+ ScintillaBase::Finalise();
+}
+
+void ScintillaQt::SelectionChanged()
+{
+ bool nowPrimary = QApplication::clipboard()->ownsSelection();
+ if (nowPrimary != primarySelection) {
+ primarySelection = nowPrimary;
+ Redraw();
+ }
+}
+
+bool ScintillaQt::DragThreshold(Point ptStart, Point ptNow)
+{
+ int xMove = abs(ptStart.x - ptNow.x);
+ int yMove = abs(ptStart.y - ptNow.y);
+ return (xMove > QApplication::startDragDistance()) ||
+ (yMove > QApplication::startDragDistance());
+}
+
+static QString StringFromSelectedText(const SelectionText &selectedText)
+{
+ if (selectedText.codePage == SC_CP_UTF8) {
+ return QString::fromUtf8(selectedText.s, selectedText.len-1);
+ } else {
+ QTextCodec *codec = QTextCodec::codecForName(
+ CharacterSetID(selectedText.characterSet));
+ return codec->toUnicode(selectedText.s, selectedText.len-1);
+ }
+}
+
+static void AddRectangularToMime(QMimeData *mimeData, QString su)
+{
+#if defined(Q_OS_WIN)
+ // Add an empty marker
+ mimeData->setData(sMSDEVColumnSelect, QByteArray());
+#elif defined(Q_OS_MAC)
+ // OS X gets marker + data to work with other implementations.
+ // Don't understand how this works but it does - the
+ // clipboard format is supposed to be UTF-16, not UTF-8.
+ mimeData->setData(sScintillaRecMimeType, su.toUtf8());
+#else
+ Q_UNUSED(su);
+ // Linux
+ // Add an empty marker
+ mimeData->setData(sMimeRectangularMarker, QByteArray());
+#endif
+}
+
+static bool IsRectangularInMime(const QMimeData *mimeData)
+{
+ QStringList formats = mimeData->formats();
+ for (int i = 0; i < formats.size(); ++i) {
+#if defined(Q_OS_WIN)
+ // Windows rectangular markers
+ // If rectangular copies made by this application, see base name.
+ if (formats[i] == sMSDEVColumnSelect)
+ return true;
+ // Otherwise see wrapped name.
+ if (formats[i] == sWrappedMSDEVColumnSelect)
+ return true;
+#elif defined(Q_OS_MAC)
+ if (formats[i] == sScintillaRecMimeType)
+ return true;
+#else
+ // Linux
+ if (formats[i] == sMimeRectangularMarker)
+ return true;
+#endif
+ }
+ return false;
+}
+
+bool ScintillaQt::ValidCodePage(int codePage) const
+{
+ return codePage == 0
+ || codePage == SC_CP_UTF8
+ || codePage == 932
+ || codePage == 936
+ || codePage == 949
+ || codePage == 950
+ || codePage == 1361;
+}
+
+
+void ScintillaQt::ScrollText(int linesToMove)
+{
+ int dy = vs.lineHeight * (linesToMove);
+ scrollArea->viewport()->scroll(0, dy);
+}
+
+void ScintillaQt::SetVerticalScrollPos()
+{
+ scrollArea->verticalScrollBar()->setValue(topLine);
+ emit verticalScrolled(topLine);
+}
+
+void ScintillaQt::SetHorizontalScrollPos()
+{
+ scrollArea->horizontalScrollBar()->setValue(xOffset);
+ emit horizontalScrolled(xOffset);
+}
+
+bool ScintillaQt::ModifyScrollBars(int nMax, int nPage)
+{
+ bool modified = false;
+
+ int vNewPage = nPage;
+ int vNewMax = nMax - vNewPage + 1;
+ if (vMax != vNewMax || vPage != vNewPage) {
+ vMax = vNewMax;
+ vPage = vNewPage;
+ modified = true;
+
+ scrollArea->verticalScrollBar()->setMaximum(vMax);
+ scrollArea->verticalScrollBar()->setPageStep(vPage);
+ emit verticalRangeChanged(vMax, vPage);
+ }
+
+ int hNewPage = GetTextRectangle().Width();
+ int hNewMax = (scrollWidth > hNewPage) ? scrollWidth - hNewPage : 0;
+ int charWidth = vs.styles[STYLE_DEFAULT].aveCharWidth;
+ if (hMax != hNewMax || hPage != hNewPage ||
+ scrollArea->horizontalScrollBar()->singleStep() != charWidth) {
+ hMax = hNewMax;
+ hPage = hNewPage;
+ modified = true;
+
+ scrollArea->horizontalScrollBar()->setMaximum(hMax);
+ scrollArea->horizontalScrollBar()->setPageStep(hPage);
+ scrollArea->horizontalScrollBar()->setSingleStep(charWidth);
+ emit horizontalRangeChanged(hMax, hPage);
+ }
+
+ return modified;
+}
+
+void ScintillaQt::ReconfigureScrollBars()
+{
+ if (verticalScrollBarVisible) {
+ scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ } else {
+ scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ }
+
+ if (horizontalScrollBarVisible && (wrapState == eWrapNone)) {
+ scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ } else {
+ scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ }
+}
+
+void ScintillaQt::CopyToModeClipboard(const SelectionText &selectedText, QClipboard::Mode clipboardMode_)
+{
+ QClipboard *clipboard = QApplication::clipboard();
+ clipboard->clear(clipboardMode_);
+ QString su = StringFromSelectedText(selectedText);
+ QMimeData *mimeData = new QMimeData();
+ mimeData->setText(su);
+ if (selectedText.rectangular) {
+ AddRectangularToMime(mimeData, su);
+ }
+
+ // Allow client code to add additional data (e.g rich text).
+ emit aboutToCopy(mimeData);
+
+ clipboard->setMimeData(mimeData, clipboardMode_);
+}
+
+void ScintillaQt::Copy()
+{
+ if (!sel.Empty()) {
+ SelectionText st;
+ CopySelectionRange(&st);
+ CopyToClipboard(st);
+ }
+}
+
+void ScintillaQt::CopyToClipboard(const SelectionText &selectedText)
+{
+ CopyToModeClipboard(selectedText, QClipboard::Clipboard);
+}
+
+void ScintillaQt::PasteFromMode(QClipboard::Mode clipboardMode_)
+{
+ QClipboard *clipboard = QApplication::clipboard();
+ const QMimeData *mimeData = clipboard->mimeData(clipboardMode_);
+ bool isRectangular = IsRectangularInMime(mimeData);
+ QString text = clipboard->text(clipboardMode_);
+ QByteArray utext = BytesForDocument(text);
+ int len = utext.length();
+ char *dest = Document::TransformLineEnds(&len, utext, len, pdoc->eolMode);
+ SelectionText selText;
+ selText.Set(dest, len, pdoc->dbcsCodePage, CharacterSetOfDocument(), isRectangular, false);
+
+ UndoGroup ug(pdoc);
+ ClearSelection(multiPasteMode == SC_MULTIPASTE_EACH);
+ SelectionPosition selStart = sel.IsRectangular() ?
+ sel.Rectangular().Start() :
+ sel.Range(sel.Main()).Start();
+ if (selText.rectangular) {
+ PasteRectangular(selStart, selText.s, selText.len);
+ } else {
+ InsertPaste(selStart, selText.s, selText.len);
+ }
+ EnsureCaretVisible();
+}
+
+void ScintillaQt::Paste()
+{
+ PasteFromMode(QClipboard::Clipboard);
+}
+
+void ScintillaQt::ClaimSelection()
+{
+ if (QApplication::clipboard()->supportsSelection()) {
+ // X Windows has a 'primary selection' as well as the clipboard.
+ // Whenever the user selects some text, we become the primary selection
+ if (!sel.Empty()) {
+ primarySelection = true;
+ SelectionText st;
+ CopySelectionRange(&st);
+ CopyToModeClipboard(st, QClipboard::Selection);
+ } else {
+ primarySelection = false;
+ }
+ }
+}
+
+void ScintillaQt::NotifyChange()
+{
+ emit notifyChange();
+ emit command(
+ Platform::LongFromTwoShorts(GetCtrlID(), SCEN_CHANGE),
+ reinterpret_cast<sptr_t>(wMain.GetID()));
+}
+
+void ScintillaQt::NotifyFocus(bool focus)
+{
+ emit command(
+ Platform::LongFromTwoShorts
+ (GetCtrlID(), focus ? SCEN_SETFOCUS : SCEN_KILLFOCUS),
+ reinterpret_cast<sptr_t>(wMain.GetID()));
+}
+
+void ScintillaQt::NotifyParent(SCNotification scn)
+{
+ scn.nmhdr.hwndFrom = wMain.GetID();
+ scn.nmhdr.idFrom = GetCtrlID();
+ emit notifyParent(scn);
+}
+
+void ScintillaQt::SetTicking(bool on)
+{
+ QTimer *qTimer;
+ if (timer.ticking != on) {
+ timer.ticking = on;
+ if (timer.ticking) {
+ qTimer = new QTimer;
+ connect(qTimer, SIGNAL(timeout()), this, SLOT(tick()));
+ qTimer->start(timer.tickSize);
+ timer.tickerID = qTimer;
+ } else {
+ qTimer = static_cast<QTimer *>(timer.tickerID);
+ qTimer->stop();
+ disconnect(qTimer, SIGNAL(timeout()), 0, 0);
+ delete qTimer;
+ timer.tickerID = 0;
+ }
+ }
+ timer.ticksToWait = caret.period;
+}
+
+void ScintillaQt::onIdle()
+{
+ bool continueIdling = Idle();
+ if (!continueIdling) {
+ SetIdle(false);
+ }
+}
+
+bool ScintillaQt::SetIdle(bool on)
+{
+ QTimer *qIdle;
+ if (on) {
+ // Start idler, if it's not running.
+ if (!idler.state) {
+ idler.state = true;
+ qIdle = new QTimer;
+ connect(qIdle, SIGNAL(timeout()), this, SLOT(onIdle()));
+ qIdle->start(0);
+ idler.idlerID = qIdle;
+ }
+ } else {
+ // Stop idler, if it's running
+ if (idler.state) {
+ idler.state = false;
+ qIdle = static_cast<QTimer *>(idler.idlerID);
+ qIdle->stop();
+ disconnect(qIdle, SIGNAL(timeout()), 0, 0);
+ delete qIdle;
+ idler.idlerID = 0;
+ }
+ }
+ return true;
+}
+
+int ScintillaQt::CharacterSetOfDocument() const
+{
+ return vs.styles[STYLE_DEFAULT].characterSet;
+}
+
+const char *ScintillaQt::CharacterSetIDOfDocument() const
+{
+ return CharacterSetID(CharacterSetOfDocument());
+}
+
+QString ScintillaQt::StringFromDocument(const char *s) const
+{
+ if (IsUnicodeMode()) {
+ return QString::fromUtf8(s);
+ } else {
+ QTextCodec *codec = QTextCodec::codecForName(
+ CharacterSetID(CharacterSetOfDocument()));
+ return codec->toUnicode(s);
+ }
+}
+
+QByteArray ScintillaQt::BytesForDocument(const QString &text) const
+{
+ if (IsUnicodeMode()) {
+ return text.toUtf8();
+ } else {
+ QTextCodec *codec = QTextCodec::codecForName(
+ CharacterSetID(CharacterSetOfDocument()));
+ return codec->fromUnicode(text);
+ }
+}
+
+
+class CaseFolderUTF8 : public CaseFolderTable {
+public:
+ CaseFolderUTF8() {
+ StandardASCII();
+ }
+ virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) {
+ if ((lenMixed == 1) && (sizeFolded > 0)) {
+ folded[0] = mapping[static_cast<unsigned char>(mixed[0])];
+ return 1;
+ } else {
+ QString su = QString::fromUtf8(mixed, lenMixed);
+ QString suFolded = su.toCaseFolded();
+ QByteArray bytesFolded = suFolded.toUtf8();
+ if (bytesFolded.length() < static_cast<int>(sizeFolded)) {
+ memcpy(folded, bytesFolded, bytesFolded.length());
+ return bytesFolded.length();
+ } else {
+ folded[0] = '\0';
+ return 0;
+ }
+ }
+ }
+};
+
+class CaseFolderDBCS : public CaseFolderTable {
+ QTextCodec *codec;
+public:
+ CaseFolderDBCS(QTextCodec *codec_) : codec(codec_) {
+ StandardASCII();
+ }
+ virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) {
+ if ((lenMixed == 1) && (sizeFolded > 0)) {
+ folded[0] = mapping[static_cast<unsigned char>(mixed[0])];
+ return 1;
+ } else if (codec) {
+ QString su = codec->toUnicode(mixed, lenMixed);
+ QString suFolded = su.toCaseFolded();
+ QByteArray bytesFolded = codec->fromUnicode(suFolded);
+
+ if (bytesFolded.length() < static_cast<int>(sizeFolded)) {
+ memcpy(folded, bytesFolded, bytesFolded.length());
+ return bytesFolded.length();
+ }
+ }
+ // Something failed so return a single NUL byte
+ folded[0] = '\0';
+ return 1;
+ }
+};
+
+CaseFolder *ScintillaQt::CaseFolderForEncoding()
+{
+ if (pdoc->dbcsCodePage == SC_CP_UTF8) {
+ return new CaseFolderUTF8();
+ } else {
+ const char *charSetBuffer = CharacterSetIDOfDocument();
+ if (charSetBuffer) {
+ if (pdoc->dbcsCodePage == 0) {
+ CaseFolderTable *pcf = new CaseFolderTable();
+ pcf->StandardASCII();
+ QTextCodec *codec = QTextCodec::codecForName(charSetBuffer);
+ // Only for single byte encodings
+ for (int i=0x80; i<0x100; i++) {
+ char sCharacter[2] = "A";
+ sCharacter[0] = i;
+ QString su = codec->toUnicode(sCharacter, 1);
+ QString suFolded = su.toCaseFolded();
+ QByteArray bytesFolded = codec->fromUnicode(suFolded);
+ if (bytesFolded.length() == 1) {
+ pcf->SetTranslation(sCharacter[0], bytesFolded[0]);
+ }
+ }
+ return pcf;
+ } else {
+ return new CaseFolderDBCS(QTextCodec::codecForName(charSetBuffer));
+ }
+ }
+ return 0;
+ }
+}
+
+std::string ScintillaQt::CaseMapString(const std::string &s, int caseMapping)
+{
+ if (s.size() == 0)
+ return std::string();
+
+ if (caseMapping == cmSame)
+ return s;
+
+ QTextCodec *codec = 0;
+ QString text;
+ if (IsUnicodeMode()) {
+ text = QString::fromUtf8(s.c_str(), s.length());
+ } else {
+ codec = QTextCodec::codecForName(CharacterSetIDOfDocument());
+ text = codec->toUnicode(s.c_str(), s.length());
+ }
+
+ if (caseMapping == cmUpper) {
+ text = text.toUpper();
+ } else {
+ text = text.toLower();
+ }
+
+ QByteArray bytes = BytesForDocument(text);
+ return std::string(bytes.data(), bytes.length());
+}
+
+void ScintillaQt::SetMouseCapture(bool on)
+{
+ // This is handled automatically by Qt
+ if (mouseDownCaptures) {
+ haveMouseCapture = on;
+ }
+}
+
+bool ScintillaQt::HaveMouseCapture()
+{
+ return haveMouseCapture;
+}
+
+void ScintillaQt::StartDrag()
+{
+ inDragDrop = ddDragging;
+ dropWentOutside = true;
+ if (drag.len) {
+ QMimeData *mimeData = new QMimeData;
+ QString sText = StringFromSelectedText(drag);
+ mimeData->setText(sText);
+ if (drag.rectangular) {
+ AddRectangularToMime(mimeData, sText);
+ }
+ // This QDrag is not freed as that causes a crash on Linux
+ QDrag *dragon = new QDrag(scrollArea);
+ dragon->setMimeData(mimeData);
+
+ Qt::DropAction dropAction = dragon->exec(Qt::CopyAction|Qt::MoveAction);
+ if ((dropAction == Qt::MoveAction) && dropWentOutside) {
+ // Remove dragged out text
+ ClearSelection();
+ }
+ }
+ inDragDrop = ddNone;
+ SetDragPosition(SelectionPosition(invalidPosition));
+}
+
+void ScintillaQt::CreateCallTipWindow(PRectangle rc)
+{
+
+ if (!ct.wCallTip.Created()) {
+ QWidget *pCallTip = new QWidget(0, Qt::ToolTip);
+ ct.wCallTip = pCallTip;
+ pCallTip->move(rc.left, rc.top);
+ pCallTip->resize(rc.Width(), rc.Height());
+ }
+}
+
+void ScintillaQt::AddToPopUp(const char *label,
+ int cmd,
+ bool enabled)
+{
+ QMenu *menu = static_cast<QMenu *>(popup.GetID());
+ QString text(label);
+
+ if (text.isEmpty()) {
+ menu->addSeparator();
+ } else {
+ QAction *action = menu->addAction(text);
+ action->setData(cmd);
+ action->setEnabled(enabled);
+ }
+
+ // Make sure the menu's signal is connected only once.
+ menu->disconnect();
+ connect(menu, SIGNAL(triggered(QAction *)),
+ this, SLOT(execCommand(QAction *)));
+}
+
+sptr_t ScintillaQt::WndProc(unsigned int message, uptr_t wParam, sptr_t lParam)
+{
+ try {
+ switch (message) {
+
+ case SCI_GRABFOCUS:
+ scrollArea->setFocus(Qt::OtherFocusReason);
+ break;
+
+ case SCI_GETDIRECTFUNCTION:
+ return reinterpret_cast<sptr_t>(DirectFunction);
+
+ case SCI_GETDIRECTPOINTER:
+ return reinterpret_cast<sptr_t>(this);
+
+#ifdef SCI_LEXER
+ case SCI_LOADLEXERLIBRARY:
+ LexerManager::GetInstance()->Load(reinterpret_cast<const char *>(lParam));
+ break;
+#endif
+
+ default:
+ return ScintillaBase::WndProc(message, wParam, lParam);
+ }
+ } catch (std::bad_alloc &) {
+ errorStatus = SC_STATUS_BADALLOC;
+ } catch (...) {
+ errorStatus = SC_STATUS_FAILURE;
+ }
+ return 0l;
+}
+
+sptr_t ScintillaQt::DefWndProc(unsigned int, uptr_t, sptr_t)
+{
+ return 0;
+}
+
+sptr_t ScintillaQt::DirectFunction(
+ ScintillaQt *sciThis, unsigned int iMessage, uptr_t wParam, sptr_t lParam)
+{
+ return sciThis->WndProc(iMessage, wParam, lParam);
+}
+
+// Additions to merge in Scientific Toolworks widget structure
+
+void ScintillaQt::PartialPaint(const PRectangle &rect)
+{
+ rcPaint = rect;
+ paintState = painting;
+ PRectangle rcClient = GetClientRectangle();
+ paintingAllText = rcPaint.Contains(rcClient);
+
+ AutoSurface surface(this);
+ Paint(surface, rcPaint);
+ surface->Release();
+
+ if (paintState == paintAbandoned) {
+ // FIXME: Failure to paint the requested rectangle in each
+ // paint event causes flicker on some platforms (Mac?)
+ // Paint rect immediately.
+ paintState = painting;
+ paintingAllText = true;
+
+ AutoSurface surface(this);
+ Paint(surface, rcPaint);
+ surface->Release();
+
+ // Queue a full repaint.
+ scrollArea->viewport()->update();
+ }
+
+ paintState = notPainting;
+}
+
+void ScintillaQt::DragEnter(const Point &point)
+{
+ SetDragPosition(SPositionFromLocation(point,
+ false, false, UserVirtualSpace()));
+}
+
+void ScintillaQt::DragMove(const Point &point)
+{
+ SetDragPosition(SPositionFromLocation(point,
+ false, false, UserVirtualSpace()));
+}
+
+void ScintillaQt::DragLeave()
+{
+ SetDragPosition(SelectionPosition(invalidPosition));
+}
+
+void ScintillaQt::Drop(const Point &point, const QMimeData *data, bool move)
+{
+ QString text = data->text();
+ bool rectangular = IsRectangularInMime(data);
+ QByteArray bytes = BytesForDocument(text);
+ int len = bytes.length();
+ char *dest = Document::TransformLineEnds(&len, bytes, len, pdoc->eolMode);
+
+ SelectionPosition movePos = SPositionFromLocation(point,
+ false, false, UserVirtualSpace());
+
+ DropAt(movePos, dest, move, rectangular);
+
+ delete []dest;
+}