2013-08-28 00:44:27 +00:00
|
|
|
//
|
|
|
|
// 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
|
2022-01-04 23:07:50 +00:00
|
|
|
// @file ScintillaEditBase.cpp - Qt widget that wraps ScintillaQt and provides events and scrolling
|
2013-08-28 00:44:27 +00:00
|
|
|
|
|
|
|
#include "ScintillaEditBase.h"
|
|
|
|
#include "ScintillaQt.h"
|
|
|
|
#include "PlatQt.h"
|
|
|
|
|
|
|
|
#include <QApplication>
|
|
|
|
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
|
|
|
|
#include <QInputContext>
|
|
|
|
#endif
|
|
|
|
#include <QPainter>
|
2019-05-04 18:14:48 +00:00
|
|
|
#include <QVarLengthArray>
|
2013-08-28 00:44:27 +00:00
|
|
|
#include <QScrollBar>
|
|
|
|
#include <QTextFormat>
|
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
constexpr int IndicatorInput = static_cast<int>(Scintilla::IndicatorNumbers::Ime);
|
|
|
|
constexpr int IndicatorTarget = IndicatorInput + 1;
|
|
|
|
constexpr int IndicatorConverted = IndicatorInput + 2;
|
|
|
|
constexpr int IndicatorUnknown = IndicatorInput + 3;
|
2015-06-07 21:19:26 +00:00
|
|
|
|
2019-05-04 18:14:48 +00:00
|
|
|
// Q_WS_MAC and Q_WS_X11 aren't defined in Qt5
|
|
|
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
|
|
|
|
#ifdef Q_OS_MAC
|
|
|
|
#define Q_WS_MAC 1
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if !defined(Q_OS_MAC) && !defined(Q_OS_WIN)
|
|
|
|
#define Q_WS_X11 1
|
2013-08-28 00:44:27 +00:00
|
|
|
#endif
|
2019-05-04 18:14:48 +00:00
|
|
|
#endif // QT_VERSION >= 5.0.0
|
|
|
|
|
|
|
|
using namespace Scintilla;
|
2022-01-04 23:07:50 +00:00
|
|
|
using namespace Scintilla::Internal;
|
2013-08-28 00:44:27 +00:00
|
|
|
|
|
|
|
ScintillaEditBase::ScintillaEditBase(QWidget *parent)
|
2022-01-04 23:07:50 +00:00
|
|
|
: QAbstractScrollArea(parent), sqt(new ScintillaQt(this)), preeditPos(-1), wheelDelta(0)
|
2013-08-28 00:44:27 +00:00
|
|
|
{
|
|
|
|
time.start();
|
|
|
|
|
|
|
|
// Set Qt defaults.
|
|
|
|
setAcceptDrops(true);
|
|
|
|
setMouseTracking(true);
|
|
|
|
setAutoFillBackground(false);
|
|
|
|
setFrameStyle(QFrame::NoFrame);
|
|
|
|
setFocusPolicy(Qt::StrongFocus);
|
|
|
|
setAttribute(Qt::WA_StaticContents);
|
2019-05-04 18:14:48 +00:00
|
|
|
viewport()->setAutoFillBackground(false);
|
2013-08-28 00:44:27 +00:00
|
|
|
setAttribute(Qt::WA_KeyCompression);
|
|
|
|
setAttribute(Qt::WA_InputMethodEnabled);
|
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
sqt->vs.indicators[IndicatorUnknown] = Indicator(IndicatorStyle::Hidden, colourIME);
|
|
|
|
sqt->vs.indicators[IndicatorInput] = Indicator(IndicatorStyle::Dots, colourIME);
|
|
|
|
sqt->vs.indicators[IndicatorConverted] = Indicator(IndicatorStyle::CompositionThick, colourIME);
|
|
|
|
sqt->vs.indicators[IndicatorTarget] = Indicator(IndicatorStyle::StraightBox, colourIME);
|
2015-06-07 21:19:26 +00:00
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
connect(sqt, SIGNAL(notifyParent(Scintilla::NotificationData)),
|
|
|
|
this, SLOT(notifyParent(Scintilla::NotificationData)));
|
2013-08-28 00:44:27 +00:00
|
|
|
|
|
|
|
// Connect scroll bars.
|
|
|
|
connect(verticalScrollBar(), SIGNAL(valueChanged(int)),
|
|
|
|
this, SLOT(scrollVertical(int)));
|
|
|
|
connect(horizontalScrollBar(), SIGNAL(valueChanged(int)),
|
|
|
|
this, SLOT(scrollHorizontal(int)));
|
|
|
|
|
|
|
|
// Connect pass-through signals.
|
|
|
|
connect(sqt, SIGNAL(horizontalRangeChanged(int,int)),
|
|
|
|
this, SIGNAL(horizontalRangeChanged(int,int)));
|
|
|
|
connect(sqt, SIGNAL(verticalRangeChanged(int,int)),
|
|
|
|
this, SIGNAL(verticalRangeChanged(int,int)));
|
|
|
|
connect(sqt, SIGNAL(horizontalScrolled(int)),
|
|
|
|
this, SIGNAL(horizontalScrolled(int)));
|
|
|
|
connect(sqt, SIGNAL(verticalScrolled(int)),
|
|
|
|
this, SIGNAL(verticalScrolled(int)));
|
|
|
|
|
|
|
|
connect(sqt, SIGNAL(notifyChange()),
|
|
|
|
this, SIGNAL(notifyChange()));
|
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
connect(sqt, SIGNAL(command(Scintilla::uptr_t,Scintilla::sptr_t)),
|
|
|
|
this, SLOT(event_command(Scintilla::uptr_t,Scintilla::sptr_t)));
|
2013-08-28 00:44:27 +00:00
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
connect(sqt, SIGNAL(aboutToCopy(QMimeData*)),
|
|
|
|
this, SIGNAL(aboutToCopy(QMimeData*)));
|
2013-08-28 00:44:27 +00:00
|
|
|
}
|
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
ScintillaEditBase::~ScintillaEditBase() = default;
|
2013-08-28 00:44:27 +00:00
|
|
|
|
|
|
|
sptr_t ScintillaEditBase::send(
|
|
|
|
unsigned int iMessage,
|
|
|
|
uptr_t wParam,
|
|
|
|
sptr_t lParam) const
|
|
|
|
{
|
2022-01-04 23:07:50 +00:00
|
|
|
return sqt->WndProc(static_cast<Message>(iMessage), wParam, lParam);
|
2013-08-28 00:44:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
sptr_t ScintillaEditBase::sends(
|
|
|
|
unsigned int iMessage,
|
|
|
|
uptr_t wParam,
|
|
|
|
const char *s) const
|
|
|
|
{
|
2022-01-04 23:07:50 +00:00
|
|
|
return sqt->WndProc(static_cast<Message>(iMessage), wParam, reinterpret_cast<sptr_t>(s));
|
2013-08-28 00:44:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ScintillaEditBase::scrollHorizontal(int value)
|
|
|
|
{
|
|
|
|
sqt->HorizontalScrollTo(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScintillaEditBase::scrollVertical(int value)
|
|
|
|
{
|
|
|
|
sqt->ScrollTo(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ScintillaEditBase::event(QEvent *event)
|
|
|
|
{
|
|
|
|
bool result = false;
|
|
|
|
|
|
|
|
if (event->type() == QEvent::KeyPress) {
|
|
|
|
// Circumvent the tab focus convention.
|
|
|
|
keyPressEvent(static_cast<QKeyEvent *>(event));
|
|
|
|
result = event->isAccepted();
|
2019-05-04 18:14:48 +00:00
|
|
|
} else if (event->type() == QEvent::Show) {
|
|
|
|
setMouseTracking(true);
|
|
|
|
result = QAbstractScrollArea::event(event);
|
2013-08-28 00:44:27 +00:00
|
|
|
} else if (event->type() == QEvent::Hide) {
|
|
|
|
setMouseTracking(false);
|
|
|
|
result = QAbstractScrollArea::event(event);
|
|
|
|
} else {
|
|
|
|
result = QAbstractScrollArea::event(event);
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScintillaEditBase::paintEvent(QPaintEvent *event)
|
|
|
|
{
|
|
|
|
sqt->PartialPaint(PRectFromQRect(event->rect()));
|
|
|
|
}
|
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
bool isWheelEventHorizontal(QWheelEvent *event) {
|
|
|
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
|
|
|
|
return event->angleDelta().y() == 0;
|
|
|
|
#else
|
|
|
|
return event->orientation() == Qt::Horizontal;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
int wheelEventYDelta(QWheelEvent *event) {
|
|
|
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
|
|
|
|
return event->angleDelta().y();
|
|
|
|
#else
|
|
|
|
return event->delta();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2013-08-28 00:44:27 +00:00
|
|
|
void ScintillaEditBase::wheelEvent(QWheelEvent *event)
|
|
|
|
{
|
2022-01-04 23:07:50 +00:00
|
|
|
if (isWheelEventHorizontal(event)) {
|
2023-02-09 16:57:24 +00:00
|
|
|
QAbstractScrollArea::wheelEvent(event);
|
2013-08-28 00:44:27 +00:00
|
|
|
} else {
|
|
|
|
if (QApplication::keyboardModifiers() & Qt::ControlModifier) {
|
|
|
|
// Zoom! We play with the font sizes in the styles.
|
|
|
|
// Number of steps/line is ignored, we just care if sizing up or down
|
2022-01-04 23:07:50 +00:00
|
|
|
if (wheelEventYDelta(event) > 0) {
|
|
|
|
sqt->KeyCommand(Message::ZoomIn);
|
2013-08-28 00:44:27 +00:00
|
|
|
} else {
|
2022-01-04 23:07:50 +00:00
|
|
|
sqt->KeyCommand(Message::ZoomOut);
|
2013-08-28 00:44:27 +00:00
|
|
|
}
|
|
|
|
} else {
|
2023-02-09 16:57:24 +00:00
|
|
|
// Scroll
|
|
|
|
QAbstractScrollArea::wheelEvent(event);
|
2013-08-28 00:44:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScintillaEditBase::focusInEvent(QFocusEvent *event)
|
|
|
|
{
|
|
|
|
sqt->SetFocusState(true);
|
|
|
|
|
|
|
|
QAbstractScrollArea::focusInEvent(event);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScintillaEditBase::focusOutEvent(QFocusEvent *event)
|
|
|
|
{
|
|
|
|
sqt->SetFocusState(false);
|
|
|
|
|
|
|
|
QAbstractScrollArea::focusOutEvent(event);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScintillaEditBase::resizeEvent(QResizeEvent *)
|
|
|
|
{
|
|
|
|
sqt->ChangeSize();
|
|
|
|
emit resized();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScintillaEditBase::keyPressEvent(QKeyEvent *event)
|
|
|
|
{
|
|
|
|
// All keystrokes containing the meta modifier are
|
|
|
|
// assumed to be shortcuts not handled by scintilla.
|
|
|
|
if (QApplication::keyboardModifiers() & Qt::MetaModifier) {
|
|
|
|
QAbstractScrollArea::keyPressEvent(event);
|
|
|
|
emit keyPressed(event);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int key = 0;
|
|
|
|
switch (event->key()) {
|
|
|
|
case Qt::Key_Down: key = SCK_DOWN; break;
|
|
|
|
case Qt::Key_Up: key = SCK_UP; break;
|
|
|
|
case Qt::Key_Left: key = SCK_LEFT; break;
|
|
|
|
case Qt::Key_Right: key = SCK_RIGHT; break;
|
|
|
|
case Qt::Key_Home: key = SCK_HOME; break;
|
|
|
|
case Qt::Key_End: key = SCK_END; break;
|
|
|
|
case Qt::Key_PageUp: key = SCK_PRIOR; break;
|
|
|
|
case Qt::Key_PageDown: key = SCK_NEXT; break;
|
|
|
|
case Qt::Key_Delete: key = SCK_DELETE; break;
|
|
|
|
case Qt::Key_Insert: key = SCK_INSERT; break;
|
|
|
|
case Qt::Key_Escape: key = SCK_ESCAPE; break;
|
|
|
|
case Qt::Key_Backspace: key = SCK_BACK; break;
|
|
|
|
case Qt::Key_Plus: key = SCK_ADD; break;
|
|
|
|
case Qt::Key_Minus: key = SCK_SUBTRACT; break;
|
|
|
|
case Qt::Key_Backtab: // fall through
|
|
|
|
case Qt::Key_Tab: key = SCK_TAB; break;
|
|
|
|
case Qt::Key_Enter: // fall through
|
|
|
|
case Qt::Key_Return: key = SCK_RETURN; break;
|
|
|
|
case Qt::Key_Control: key = 0; break;
|
|
|
|
case Qt::Key_Alt: key = 0; break;
|
|
|
|
case Qt::Key_Shift: key = 0; break;
|
|
|
|
case Qt::Key_Meta: key = 0; break;
|
|
|
|
default: key = event->key(); break;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool shift = QApplication::keyboardModifiers() & Qt::ShiftModifier;
|
|
|
|
bool ctrl = QApplication::keyboardModifiers() & Qt::ControlModifier;
|
|
|
|
bool alt = QApplication::keyboardModifiers() & Qt::AltModifier;
|
|
|
|
|
|
|
|
bool consumed = false;
|
2022-01-04 23:07:50 +00:00
|
|
|
bool added = sqt->KeyDownWithModifiers(static_cast<Keys>(key),
|
2022-08-27 07:35:52 +00:00
|
|
|
ModifierFlags(shift, ctrl, alt),
|
2019-05-04 18:14:48 +00:00
|
|
|
&consumed) != 0;
|
2013-08-28 00:44:27 +00:00
|
|
|
if (!consumed)
|
|
|
|
consumed = added;
|
|
|
|
|
|
|
|
if (!consumed) {
|
|
|
|
// Don't insert text if the control key was pressed unless
|
|
|
|
// it was pressed in conjunction with alt for AltGr emulation.
|
|
|
|
bool input = (!ctrl || alt);
|
|
|
|
|
|
|
|
// Additionally, on non-mac platforms, don't insert text
|
|
|
|
// if the alt key was pressed unless control is also present.
|
|
|
|
// On mac alt can be used to insert special characters.
|
|
|
|
#ifndef Q_WS_MAC
|
|
|
|
input &= (!alt || ctrl);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
QString text = event->text();
|
|
|
|
if (input && !text.isEmpty() && text[0].isPrint()) {
|
2023-05-31 23:11:12 +00:00
|
|
|
const int strLen = text.length();
|
|
|
|
for (int i = 0; i < strLen;) {
|
|
|
|
const int ucWidth = text.at(i).isHighSurrogate() ? 2 : 1;
|
|
|
|
const QString oneCharUTF16 = text.mid(i, ucWidth);
|
|
|
|
const QByteArray oneChar = sqt->BytesForDocument(oneCharUTF16);
|
|
|
|
|
|
|
|
sqt->InsertCharacter(std::string_view(oneChar.data(), oneChar.length()), CharacterSource::DirectInput);
|
|
|
|
i += ucWidth;
|
|
|
|
}
|
2013-08-28 00:44:27 +00:00
|
|
|
} else {
|
|
|
|
event->ignore();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
emit keyPressed(event);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int modifierTranslated(int sciModifier)
|
|
|
|
{
|
|
|
|
switch (sciModifier) {
|
|
|
|
case SCMOD_SHIFT:
|
|
|
|
return Qt::ShiftModifier;
|
|
|
|
case SCMOD_CTRL:
|
|
|
|
return Qt::ControlModifier;
|
|
|
|
case SCMOD_ALT:
|
|
|
|
return Qt::AltModifier;
|
|
|
|
case SCMOD_SUPER:
|
|
|
|
return Qt::MetaModifier;
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScintillaEditBase::mousePressEvent(QMouseEvent *event)
|
|
|
|
{
|
|
|
|
Point pos = PointFromQPoint(event->pos());
|
|
|
|
|
|
|
|
emit buttonPressed(event);
|
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
if (event->button() == Qt::MiddleButton &&
|
2013-08-28 00:44:27 +00:00
|
|
|
QApplication::clipboard()->supportsSelection()) {
|
|
|
|
SelectionPosition selPos = sqt->SPositionFromLocation(
|
|
|
|
pos, false, false, sqt->UserVirtualSpace());
|
|
|
|
sqt->sel.Clear();
|
|
|
|
sqt->SetSelection(selPos, selPos);
|
|
|
|
sqt->PasteFromMode(QClipboard::Selection);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-05-04 18:14:48 +00:00
|
|
|
if (event->button() == Qt::LeftButton) {
|
2013-08-28 00:44:27 +00:00
|
|
|
bool shift = QApplication::keyboardModifiers() & Qt::ShiftModifier;
|
|
|
|
bool ctrl = QApplication::keyboardModifiers() & Qt::ControlModifier;
|
|
|
|
bool alt = QApplication::keyboardModifiers() & modifierTranslated(sqt->rectangularSelectionModifier);
|
|
|
|
|
2022-08-27 07:35:52 +00:00
|
|
|
sqt->ButtonDownWithModifiers(pos, time.elapsed(), ModifierFlags(shift, ctrl, alt));
|
2019-05-04 18:14:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (event->button() == Qt::RightButton) {
|
|
|
|
sqt->RightButtonDownWithModifiers(pos, time.elapsed(), ModifiersOfKeyboard());
|
2013-08-28 00:44:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScintillaEditBase::mouseReleaseEvent(QMouseEvent *event)
|
|
|
|
{
|
2022-01-04 23:07:50 +00:00
|
|
|
const QPoint point = event->pos();
|
2013-08-28 00:44:27 +00:00
|
|
|
if (event->button() == Qt::LeftButton)
|
2022-01-04 23:07:50 +00:00
|
|
|
sqt->ButtonUpWithModifiers(PointFromQPoint(point), time.elapsed(), ModifiersOfKeyboard());
|
2013-08-28 00:44:27 +00:00
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
const sptr_t pos = send(SCI_POSITIONFROMPOINT, point.x(), point.y());
|
|
|
|
const sptr_t line = send(SCI_LINEFROMPOSITION, pos);
|
2013-08-28 00:44:27 +00:00
|
|
|
int modifiers = QApplication::keyboardModifiers();
|
|
|
|
|
|
|
|
emit textAreaClicked(line, modifiers);
|
|
|
|
emit buttonReleased(event);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScintillaEditBase::mouseDoubleClickEvent(QMouseEvent *event)
|
|
|
|
{
|
|
|
|
// Scintilla does its own double-click detection.
|
|
|
|
mousePressEvent(event);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScintillaEditBase::mouseMoveEvent(QMouseEvent *event)
|
|
|
|
{
|
|
|
|
Point pos = PointFromQPoint(event->pos());
|
2015-06-07 21:19:26 +00:00
|
|
|
|
|
|
|
bool shift = QApplication::keyboardModifiers() & Qt::ShiftModifier;
|
|
|
|
bool ctrl = QApplication::keyboardModifiers() & Qt::ControlModifier;
|
|
|
|
bool alt = QApplication::keyboardModifiers() & modifierTranslated(sqt->rectangularSelectionModifier);
|
|
|
|
|
2022-08-27 07:35:52 +00:00
|
|
|
const KeyMod modifiers = ModifierFlags(shift, ctrl, alt);
|
2015-06-07 21:19:26 +00:00
|
|
|
|
2019-05-04 18:14:48 +00:00
|
|
|
sqt->ButtonMoveWithModifiers(pos, time.elapsed(), modifiers);
|
2013-08-28 00:44:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ScintillaEditBase::contextMenuEvent(QContextMenuEvent *event)
|
|
|
|
{
|
|
|
|
Point pos = PointFromQPoint(event->globalPos());
|
|
|
|
Point pt = PointFromQPoint(event->pos());
|
2019-05-04 18:14:48 +00:00
|
|
|
if (!sqt->PointInSelection(pt)) {
|
2013-08-28 00:44:27 +00:00
|
|
|
sqt->SetEmptySelection(sqt->PositionFromLocation(pt));
|
2019-05-04 18:14:48 +00:00
|
|
|
}
|
|
|
|
if (sqt->ShouldDisplayPopup(pt)) {
|
|
|
|
sqt->ContextMenu(pos);
|
2023-09-22 09:32:35 +00:00
|
|
|
event->accept();
|
|
|
|
} else {
|
|
|
|
event->ignore();
|
2019-05-04 18:14:48 +00:00
|
|
|
}
|
2013-08-28 00:44:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ScintillaEditBase::dragEnterEvent(QDragEnterEvent *event)
|
|
|
|
{
|
2019-05-04 18:14:48 +00:00
|
|
|
if (event->mimeData()->hasUrls()) {
|
|
|
|
event->acceptProposedAction();
|
|
|
|
} else if (event->mimeData()->hasText()) {
|
2013-08-28 00:44:27 +00:00
|
|
|
event->acceptProposedAction();
|
|
|
|
|
|
|
|
Point point = PointFromQPoint(event->pos());
|
|
|
|
sqt->DragEnter(point);
|
|
|
|
} else {
|
|
|
|
event->ignore();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScintillaEditBase::dragLeaveEvent(QDragLeaveEvent * /* event */)
|
|
|
|
{
|
|
|
|
sqt->DragLeave();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScintillaEditBase::dragMoveEvent(QDragMoveEvent *event)
|
|
|
|
{
|
2019-05-04 18:14:48 +00:00
|
|
|
if (event->mimeData()->hasUrls()) {
|
|
|
|
event->acceptProposedAction();
|
|
|
|
} else if (event->mimeData()->hasText()) {
|
2013-08-28 00:44:27 +00:00
|
|
|
event->acceptProposedAction();
|
|
|
|
|
|
|
|
Point point = PointFromQPoint(event->pos());
|
|
|
|
sqt->DragMove(point);
|
|
|
|
} else {
|
|
|
|
event->ignore();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScintillaEditBase::dropEvent(QDropEvent *event)
|
|
|
|
{
|
2019-05-04 18:14:48 +00:00
|
|
|
if (event->mimeData()->hasUrls()) {
|
|
|
|
event->acceptProposedAction();
|
|
|
|
sqt->DropUrls(event->mimeData());
|
|
|
|
} else if (event->mimeData()->hasText()) {
|
2013-08-28 00:44:27 +00:00
|
|
|
event->acceptProposedAction();
|
|
|
|
|
|
|
|
Point point = PointFromQPoint(event->pos());
|
|
|
|
bool move = (event->source() == this &&
|
|
|
|
event->proposedAction() == Qt::MoveAction);
|
|
|
|
sqt->Drop(point, event->mimeData(), move);
|
|
|
|
} else {
|
|
|
|
event->ignore();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-07 21:19:26 +00:00
|
|
|
bool ScintillaEditBase::IsHangul(const QChar qchar)
|
|
|
|
{
|
2022-01-04 23:07:50 +00:00
|
|
|
unsigned int unicode = qchar.unicode();
|
2015-06-07 21:19:26 +00:00
|
|
|
// Korean character ranges used for preedit chars.
|
|
|
|
// http://www.programminginkorean.com/programming/hangul-in-unicode/
|
|
|
|
const bool HangulJamo = (0x1100 <= unicode && unicode <= 0x11FF);
|
|
|
|
const bool HangulCompatibleJamo = (0x3130 <= unicode && unicode <= 0x318F);
|
|
|
|
const bool HangulJamoExtendedA = (0xA960 <= unicode && unicode <= 0xA97F);
|
|
|
|
const bool HangulJamoExtendedB = (0xD7B0 <= unicode && unicode <= 0xD7FF);
|
|
|
|
const bool HangulSyllable = (0xAC00 <= unicode && unicode <= 0xD7A3);
|
|
|
|
return HangulJamo || HangulCompatibleJamo || HangulSyllable ||
|
2019-05-04 18:14:48 +00:00
|
|
|
HangulJamoExtendedA || HangulJamoExtendedB;
|
2015-06-07 21:19:26 +00:00
|
|
|
}
|
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
void ScintillaEditBase::MoveImeCarets(Scintilla::Position offset)
|
2015-06-07 21:19:26 +00:00
|
|
|
{
|
|
|
|
// Move carets relatively by bytes
|
|
|
|
for (size_t r=0; r < sqt->sel.Count(); r++) {
|
2022-01-04 23:07:50 +00:00
|
|
|
const Sci::Position positionInsert = sqt->sel.Range(r).Start().Position();
|
2015-06-07 21:19:26 +00:00
|
|
|
sqt->sel.Range(r).caret.SetPosition(positionInsert + offset);
|
|
|
|
sqt->sel.Range(r).anchor.SetPosition(positionInsert + offset);
|
|
|
|
}
|
|
|
|
}
|
2019-05-04 18:14:48 +00:00
|
|
|
|
|
|
|
void ScintillaEditBase::DrawImeIndicator(int indicator, int len)
|
2015-06-07 21:19:26 +00:00
|
|
|
{
|
|
|
|
// Emulate the visual style of IME characters with indicators.
|
|
|
|
// Draw an indicator on the character before caret by the character bytes of len
|
2019-07-21 13:26:02 +00:00
|
|
|
// so it should be called after InsertCharacter().
|
2015-06-07 21:19:26 +00:00
|
|
|
// It does not affect caret positions.
|
2022-01-04 23:07:50 +00:00
|
|
|
if (indicator < INDICATOR_CONTAINER || indicator > INDICATOR_MAX) {
|
2015-06-07 21:19:26 +00:00
|
|
|
return;
|
|
|
|
}
|
2019-05-04 18:14:48 +00:00
|
|
|
sqt->pdoc->DecorationSetCurrentIndicator(indicator);
|
2015-06-07 21:19:26 +00:00
|
|
|
for (size_t r=0; r< sqt-> sel.Count(); r++) {
|
2022-01-04 23:07:50 +00:00
|
|
|
const Sci::Position positionInsert = sqt->sel.Range(r).Start().Position();
|
2015-06-07 21:19:26 +00:00
|
|
|
sqt->pdoc->DecorationFillRange(positionInsert - len, 1, len);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-04 18:14:48 +00:00
|
|
|
static int GetImeCaretPos(QInputMethodEvent *event)
|
|
|
|
{
|
|
|
|
foreach (QInputMethodEvent::Attribute attr, event->attributes()) {
|
|
|
|
if (attr.type == QInputMethodEvent::Cursor)
|
|
|
|
return attr.start;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static std::vector<int> MapImeIndicators(QInputMethodEvent *event)
|
|
|
|
{
|
2022-01-04 23:07:50 +00:00
|
|
|
std::vector<int> imeIndicator(event->preeditString().size(), IndicatorUnknown);
|
2019-05-04 18:14:48 +00:00
|
|
|
foreach (QInputMethodEvent::Attribute attr, event->attributes()) {
|
|
|
|
if (attr.type == QInputMethodEvent::TextFormat) {
|
|
|
|
QTextFormat format = attr.value.value<QTextFormat>();
|
|
|
|
QTextCharFormat charFormat = format.toCharFormat();
|
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
int indicator = IndicatorUnknown;
|
2019-05-04 18:14:48 +00:00
|
|
|
switch (charFormat.underlineStyle()) {
|
|
|
|
case QTextCharFormat::NoUnderline: // win32, linux
|
|
|
|
case QTextCharFormat::SingleUnderline: // osx
|
|
|
|
case QTextCharFormat::DashUnderline: // win32, linux
|
2022-01-04 23:07:50 +00:00
|
|
|
indicator = IndicatorInput;
|
2019-05-04 18:14:48 +00:00
|
|
|
break;
|
|
|
|
case QTextCharFormat::DotLine:
|
|
|
|
case QTextCharFormat::DashDotLine:
|
|
|
|
case QTextCharFormat::WaveUnderline:
|
|
|
|
case QTextCharFormat::SpellCheckUnderline:
|
2022-01-04 23:07:50 +00:00
|
|
|
indicator = IndicatorConverted;
|
2019-05-04 18:14:48 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2022-01-04 23:07:50 +00:00
|
|
|
indicator = IndicatorUnknown;
|
2019-05-04 18:14:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (format.hasProperty(QTextFormat::BackgroundBrush)) // win32, linux
|
2022-01-04 23:07:50 +00:00
|
|
|
indicator = IndicatorTarget;
|
2019-05-04 18:14:48 +00:00
|
|
|
|
|
|
|
#ifdef Q_OS_OSX
|
|
|
|
if (charFormat.underlineStyle() == QTextCharFormat::SingleUnderline) {
|
|
|
|
QColor uc = charFormat.underlineColor();
|
|
|
|
if (uc.lightness() < 2) { // osx
|
2022-01-04 23:07:50 +00:00
|
|
|
indicator = IndicatorTarget;
|
2019-05-04 18:14:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
for (int i = attr.start; i < attr.start+attr.length; i++) {
|
|
|
|
imeIndicator[i] = indicator;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return imeIndicator;
|
|
|
|
}
|
|
|
|
|
2013-08-28 00:44:27 +00:00
|
|
|
void ScintillaEditBase::inputMethodEvent(QInputMethodEvent *event)
|
|
|
|
{
|
2015-06-07 21:19:26 +00:00
|
|
|
// Copy & paste by johnsonj with a lot of helps of Neil
|
|
|
|
// Great thanks for my forerunners, jiniya and BLUEnLIVE
|
|
|
|
|
2019-05-04 18:14:48 +00:00
|
|
|
if (sqt->pdoc->IsReadOnly() || sqt->SelectionContainsProtected()) {
|
|
|
|
// Here, a canceling and/or completing composition function is needed.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool initialCompose = false;
|
2015-06-07 21:19:26 +00:00
|
|
|
if (sqt->pdoc->TentativeActive()) {
|
|
|
|
sqt->pdoc->TentativeUndo();
|
|
|
|
} else {
|
|
|
|
// No tentative undo means start of this composition so
|
|
|
|
// Fill in any virtual spaces.
|
2019-05-04 18:14:48 +00:00
|
|
|
initialCompose = true;
|
2013-08-28 00:44:27 +00:00
|
|
|
}
|
|
|
|
|
2015-06-07 21:19:26 +00:00
|
|
|
sqt->view.imeCaretBlockOverride = false;
|
2023-05-31 23:11:12 +00:00
|
|
|
preeditPos = -1; // reset not to interrupt Qt::ImCursorRectangle.
|
2015-06-07 21:19:26 +00:00
|
|
|
|
Update: Scintilla 5.3.6 and Lexilla 5.2.6
update to Scinitlla Release 5.3.6 (https://www.scintilla.org/scintilla536.zip)
Released 26 July 2023.
Redraw calltip after showing as didn't update when size of new text exactly same as previous. Feature #1486.
On Win32 fix reverse arrow cursor when scaled. Bug #2382.
On Win32 hide cursor when typing if that system preference has been chosen. Bug #2333.
On Win32 and Qt, stop aligning IME candidate window to target. It is now always aligned to start of composition string. This undoes part of feature #1300. Feature #1488, Bug #2391, Feature #1300.
On Qt, for IMEs, update micro focus when selection changes. This may move the location of IME popups to align with the caret.
On Qt, implement replacement for IMEs which may help with actions like reconversion. This is similar to delete-surrounding on GTK.
and Lexilla Release 5.2.6 (https://www.scintilla.org/lexilla526.zip)
Released 26 July 2023.
Include empty word list names in value returned by DescribeWordListSets and SCI_DESCRIBEKEYWORDSETS. Issue #175, Pull request #176.
Bash: style here-doc end delimiters as SCE_SH_HERE_DELIM instead of SCE_SH_HERE_Q. Issue #177.
Bash: allow '$' as last character in string. Issue #180, Pull request #181.
Bash: fix state after expansion. Highlight all numeric and file test operators. Don't highlight dash in long option as operator. Issue #182, Pull request #183.
Bash: strict checking of special parameters ($*, $@, $$, ...) with property lexer.bash.special.parameter to specify valid parameters. Issue #184, Pull request #186.
Bash: recognize keyword before redirection operators (< and >). Issue #188, Pull request #189.
Errorlist: recognize Bash diagnostic messages.
HTML: allow ASP block to terminate inside line comment. Issue #185.
HTML: fix folding with JSP/ASP.NET <%-- comment. Issue #191.
HTML: fix incremental styling of multi-line ASP.NET directive. Issue #191.
Matlab: improve arguments blocks. Add support for multiple arguments blocks. Prevent "arguments" from being keyword in function declaration line. Fix semicolon handling. Pull request #179.
Visual Prolog: add support for embedded syntax with SCE_VISUALPROLOG_EMBEDDED and SCE_VISUALPROLOG_PLACEHOLDER.
Styling of string literals changed with no differentiation between literals with quotes and those that are prefixed with "@". Quote characters are in a separate style (SCE_VISUALPROLOG_STRING_QUOTE) to contents (SCE_VISUALPROLOG_STRING).
SCE_VISUALPROLOG_CHARACTER, SCE_VISUALPROLOG_CHARACTER_TOO_MANY, SCE_VISUALPROLOG_CHARACTER_ESCAPE_ERROR, SCE_VISUALPROLOG_STRING_EOL_OPEN, and SCE_VISUALPROLOG_STRING_VERBATIM_SPECIAL were removed (replaced with SCE_VISUALPROLOG_UNUSED[1-5]). Pull request #178.
Fix #13901, fix #13911, fix #13943, close #13940
2023-07-27 17:57:12 +00:00
|
|
|
const int rpLength = event->replacementLength();
|
|
|
|
if (rpLength != 0) {
|
|
|
|
// Qt has called setCommitString().
|
|
|
|
// Make room for the string to sit in.
|
|
|
|
const int rpStart = event->replacementStart();
|
|
|
|
const Scintilla::Position rpBase = sqt->CurrentPosition();
|
|
|
|
const Scintilla::Position start = sqt->pdoc->GetRelativePositionUTF16(rpBase, rpStart);
|
|
|
|
const Scintilla::Position end = sqt->pdoc->GetRelativePositionUTF16(start, rpLength);
|
|
|
|
sqt->pdoc->DeleteChars(start, end - start);
|
|
|
|
}
|
|
|
|
|
2015-06-07 21:19:26 +00:00
|
|
|
if (!event->commitString().isEmpty()) {
|
2022-01-04 23:07:50 +00:00
|
|
|
const QString &commitStr = event->commitString();
|
|
|
|
const int commitStrLen = commitStr.length();
|
2015-06-07 21:19:26 +00:00
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
for (int i = 0; i < commitStrLen;) {
|
|
|
|
const int ucWidth = commitStr.at(i).isHighSurrogate() ? 2 : 1;
|
2015-06-07 21:19:26 +00:00
|
|
|
const QString oneCharUTF16 = commitStr.mid(i, ucWidth);
|
|
|
|
const QByteArray oneChar = sqt->BytesForDocument(oneCharUTF16);
|
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
sqt->InsertCharacter(std::string_view(oneChar.data(), oneChar.length()), CharacterSource::DirectInput);
|
2015-06-07 21:19:26 +00:00
|
|
|
i += ucWidth;
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if (!event->preeditString().isEmpty()) {
|
|
|
|
const QString preeditStr = event->preeditString();
|
2022-01-04 23:07:50 +00:00
|
|
|
const int preeditStrLen = preeditStr.length();
|
2019-07-21 13:26:02 +00:00
|
|
|
if (preeditStrLen == 0) {
|
2015-06-07 21:19:26 +00:00
|
|
|
sqt->ShowCaretAtCurrentPosition();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-05-04 18:14:48 +00:00
|
|
|
if (initialCompose)
|
|
|
|
sqt->ClearBeforeTentativeStart();
|
2015-06-07 21:19:26 +00:00
|
|
|
sqt->pdoc->TentativeStart(); // TentativeActive() from now on.
|
|
|
|
|
2023-05-31 23:11:12 +00:00
|
|
|
// Fix candidate window position at the start of preeditString.
|
|
|
|
preeditPos = sqt->CurrentPosition();
|
|
|
|
|
2019-05-04 18:14:48 +00:00
|
|
|
std::vector<int> imeIndicator = MapImeIndicators(event);
|
2015-06-07 21:19:26 +00:00
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
for (int i = 0; i < preeditStrLen;) {
|
|
|
|
const int ucWidth = preeditStr.at(i).isHighSurrogate() ? 2 : 1;
|
2015-06-07 21:19:26 +00:00
|
|
|
const QString oneCharUTF16 = preeditStr.mid(i, ucWidth);
|
|
|
|
const QByteArray oneChar = sqt->BytesForDocument(oneCharUTF16);
|
|
|
|
const int oneCharLen = oneChar.length();
|
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
sqt->InsertCharacter(std::string_view(oneChar.data(), oneCharLen), CharacterSource::TentativeInput);
|
2015-06-07 21:19:26 +00:00
|
|
|
|
|
|
|
DrawImeIndicator(imeIndicator[i], oneCharLen);
|
|
|
|
i += ucWidth;
|
2019-05-04 18:14:48 +00:00
|
|
|
}
|
2015-06-07 21:19:26 +00:00
|
|
|
|
|
|
|
// Move IME carets.
|
2019-05-04 18:14:48 +00:00
|
|
|
int imeCaretPos = GetImeCaretPos(event);
|
|
|
|
int imeEndToImeCaretU16 = imeCaretPos - preeditStrLen;
|
2022-01-04 23:07:50 +00:00
|
|
|
const Sci::Position imeCaretPosDoc = sqt->pdoc->GetRelativePositionUTF16(sqt->CurrentPosition(), imeEndToImeCaretU16);
|
2019-05-04 18:14:48 +00:00
|
|
|
|
|
|
|
MoveImeCarets(- sqt->CurrentPosition() + imeCaretPosDoc);
|
|
|
|
|
2015-06-07 21:19:26 +00:00
|
|
|
if (IsHangul(preeditStr.at(0))) {
|
2019-05-04 18:14:48 +00:00
|
|
|
#ifndef Q_OS_WIN
|
|
|
|
if (imeCaretPos > 0) {
|
|
|
|
int oneCharBefore = sqt->pdoc->GetRelativePosition(sqt->CurrentPosition(), -1);
|
|
|
|
MoveImeCarets(- sqt->CurrentPosition() + oneCharBefore);
|
|
|
|
}
|
|
|
|
#endif
|
2015-06-07 21:19:26 +00:00
|
|
|
sqt->view.imeCaretBlockOverride = true;
|
|
|
|
}
|
2019-05-04 18:14:48 +00:00
|
|
|
sqt->EnsureCaretVisible();
|
2013-08-28 00:44:27 +00:00
|
|
|
}
|
2015-06-07 21:19:26 +00:00
|
|
|
sqt->ShowCaretAtCurrentPosition();
|
2013-08-28 00:44:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QVariant ScintillaEditBase::inputMethodQuery(Qt::InputMethodQuery query) const
|
|
|
|
{
|
2022-01-04 23:07:50 +00:00
|
|
|
const Scintilla::Position pos = send(SCI_GETCURRENTPOS);
|
|
|
|
const Scintilla::Position line = send(SCI_LINEFROMPOSITION, pos);
|
2013-08-28 00:44:27 +00:00
|
|
|
|
|
|
|
switch (query) {
|
2022-01-04 23:07:50 +00:00
|
|
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
|
|
|
|
// Qt 5 renamed ImMicroFocus to ImCursorRectangle then deprecated
|
|
|
|
// ImMicroFocus. Its the same value (2) and same description.
|
|
|
|
case Qt::ImCursorRectangle:
|
|
|
|
{
|
|
|
|
const Scintilla::Position startPos = (preeditPos >= 0) ? preeditPos : pos;
|
|
|
|
const Point pt = sqt->LocationFromPosition(startPos);
|
|
|
|
const int width = static_cast<int>(send(SCI_GETCARETWIDTH));
|
|
|
|
const int height = static_cast<int>(send(SCI_TEXTHEIGHT, line));
|
|
|
|
return QRectF(pt.x, pt.y, width, height).toRect();
|
|
|
|
}
|
|
|
|
#else
|
2013-08-28 00:44:27 +00:00
|
|
|
case Qt::ImMicroFocus:
|
|
|
|
{
|
2022-01-04 23:07:50 +00:00
|
|
|
const Scintilla::Position startPos = (preeditPos >= 0) ? preeditPos : pos;
|
|
|
|
const Point pt = sqt->LocationFromPosition(startPos);
|
|
|
|
const int width = static_cast<int>(send(SCI_GETCARETWIDTH));
|
|
|
|
const int height = static_cast<int>(send(SCI_TEXTHEIGHT, line));
|
2013-08-28 00:44:27 +00:00
|
|
|
return QRect(pt.x, pt.y, width, height);
|
|
|
|
}
|
2022-01-04 23:07:50 +00:00
|
|
|
#endif
|
2013-08-28 00:44:27 +00:00
|
|
|
|
|
|
|
case Qt::ImFont:
|
|
|
|
{
|
|
|
|
char fontName[64];
|
2022-01-04 23:07:50 +00:00
|
|
|
const sptr_t style = send(SCI_GETSTYLEAT, pos);
|
|
|
|
const int len = static_cast<int>(sends(SCI_STYLEGETFONT, style, fontName));
|
|
|
|
const int size = static_cast<int>(send(SCI_STYLEGETSIZE, style));
|
|
|
|
const bool italic = send(SCI_STYLEGETITALIC, style);
|
|
|
|
const int weight = send(SCI_STYLEGETBOLD, style) ? QFont::Bold : -1;
|
2013-08-28 00:44:27 +00:00
|
|
|
return QFont(QString::fromUtf8(fontName, len), size, weight, italic);
|
|
|
|
}
|
|
|
|
|
|
|
|
case Qt::ImCursorPosition:
|
|
|
|
{
|
2022-01-04 23:07:50 +00:00
|
|
|
const Scintilla::Position paraStart = sqt->pdoc->ParaUp(pos);
|
2023-05-31 23:11:12 +00:00
|
|
|
return static_cast<int>(sqt->pdoc->CountUTF16(paraStart, pos));
|
2013-08-28 00:44:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
case Qt::ImSurroundingText:
|
|
|
|
{
|
2022-01-04 23:07:50 +00:00
|
|
|
const Scintilla::Position paraStart = sqt->pdoc->ParaUp(pos);
|
|
|
|
const Scintilla::Position paraEnd = sqt->pdoc->ParaDown(pos);
|
|
|
|
const std::string buffer = sqt->RangeText(paraStart, paraEnd);
|
|
|
|
return sqt->StringFromDocument(buffer.c_str());
|
2013-08-28 00:44:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
case Qt::ImCurrentSelection:
|
|
|
|
{
|
2023-09-22 09:32:35 +00:00
|
|
|
QVarLengthArray<char,1024> buffer(send(SCI_GETSELTEXT)+1);
|
2022-01-04 23:07:50 +00:00
|
|
|
sends(SCI_GETSELTEXT, 0, buffer.data());
|
2013-08-28 00:44:27 +00:00
|
|
|
|
|
|
|
return sqt->StringFromDocument(buffer.constData());
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
return QVariant();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
void ScintillaEditBase::notifyParent(NotificationData scn)
|
2013-08-28 00:44:27 +00:00
|
|
|
{
|
|
|
|
emit notify(&scn);
|
|
|
|
switch (scn.nmhdr.code) {
|
2022-01-04 23:07:50 +00:00
|
|
|
case Notification::StyleNeeded:
|
2013-08-28 00:44:27 +00:00
|
|
|
emit styleNeeded(scn.position);
|
|
|
|
break;
|
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
case Notification::CharAdded:
|
2013-08-28 00:44:27 +00:00
|
|
|
emit charAdded(scn.ch);
|
|
|
|
break;
|
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
case Notification::SavePointReached:
|
2013-08-28 00:44:27 +00:00
|
|
|
emit savePointChanged(false);
|
|
|
|
break;
|
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
case Notification::SavePointLeft:
|
2013-08-28 00:44:27 +00:00
|
|
|
emit savePointChanged(true);
|
|
|
|
break;
|
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
case Notification::ModifyAttemptRO:
|
2013-08-28 00:44:27 +00:00
|
|
|
emit modifyAttemptReadOnly();
|
|
|
|
break;
|
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
case Notification::Key:
|
2013-08-28 00:44:27 +00:00
|
|
|
emit key(scn.ch);
|
|
|
|
break;
|
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
case Notification::DoubleClick:
|
2013-08-28 00:44:27 +00:00
|
|
|
emit doubleClick(scn.position, scn.line);
|
|
|
|
break;
|
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
case Notification::UpdateUI:
|
Update: Scintilla 5.3.6 and Lexilla 5.2.6
update to Scinitlla Release 5.3.6 (https://www.scintilla.org/scintilla536.zip)
Released 26 July 2023.
Redraw calltip after showing as didn't update when size of new text exactly same as previous. Feature #1486.
On Win32 fix reverse arrow cursor when scaled. Bug #2382.
On Win32 hide cursor when typing if that system preference has been chosen. Bug #2333.
On Win32 and Qt, stop aligning IME candidate window to target. It is now always aligned to start of composition string. This undoes part of feature #1300. Feature #1488, Bug #2391, Feature #1300.
On Qt, for IMEs, update micro focus when selection changes. This may move the location of IME popups to align with the caret.
On Qt, implement replacement for IMEs which may help with actions like reconversion. This is similar to delete-surrounding on GTK.
and Lexilla Release 5.2.6 (https://www.scintilla.org/lexilla526.zip)
Released 26 July 2023.
Include empty word list names in value returned by DescribeWordListSets and SCI_DESCRIBEKEYWORDSETS. Issue #175, Pull request #176.
Bash: style here-doc end delimiters as SCE_SH_HERE_DELIM instead of SCE_SH_HERE_Q. Issue #177.
Bash: allow '$' as last character in string. Issue #180, Pull request #181.
Bash: fix state after expansion. Highlight all numeric and file test operators. Don't highlight dash in long option as operator. Issue #182, Pull request #183.
Bash: strict checking of special parameters ($*, $@, $$, ...) with property lexer.bash.special.parameter to specify valid parameters. Issue #184, Pull request #186.
Bash: recognize keyword before redirection operators (< and >). Issue #188, Pull request #189.
Errorlist: recognize Bash diagnostic messages.
HTML: allow ASP block to terminate inside line comment. Issue #185.
HTML: fix folding with JSP/ASP.NET <%-- comment. Issue #191.
HTML: fix incremental styling of multi-line ASP.NET directive. Issue #191.
Matlab: improve arguments blocks. Add support for multiple arguments blocks. Prevent "arguments" from being keyword in function declaration line. Fix semicolon handling. Pull request #179.
Visual Prolog: add support for embedded syntax with SCE_VISUALPROLOG_EMBEDDED and SCE_VISUALPROLOG_PLACEHOLDER.
Styling of string literals changed with no differentiation between literals with quotes and those that are prefixed with "@". Quote characters are in a separate style (SCE_VISUALPROLOG_STRING_QUOTE) to contents (SCE_VISUALPROLOG_STRING).
SCE_VISUALPROLOG_CHARACTER, SCE_VISUALPROLOG_CHARACTER_TOO_MANY, SCE_VISUALPROLOG_CHARACTER_ESCAPE_ERROR, SCE_VISUALPROLOG_STRING_EOL_OPEN, and SCE_VISUALPROLOG_STRING_VERBATIM_SPECIAL were removed (replaced with SCE_VISUALPROLOG_UNUSED[1-5]). Pull request #178.
Fix #13901, fix #13911, fix #13943, close #13940
2023-07-27 17:57:12 +00:00
|
|
|
if (FlagSet(scn.updated, Update::Selection)) {
|
|
|
|
updateMicroFocus();
|
|
|
|
}
|
2019-05-04 18:14:48 +00:00
|
|
|
emit updateUi(scn.updated);
|
2013-08-28 00:44:27 +00:00
|
|
|
break;
|
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
case Notification::Modified:
|
2013-08-28 00:44:27 +00:00
|
|
|
{
|
2022-01-04 23:07:50 +00:00
|
|
|
const bool added = FlagSet(scn.modificationType, ModificationFlags::InsertText);
|
|
|
|
const bool deleted = FlagSet(scn.modificationType, ModificationFlags::DeleteText);
|
2013-08-28 00:44:27 +00:00
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
const Scintilla::Position length = send(SCI_GETTEXTLENGTH);
|
2013-08-28 00:44:27 +00:00
|
|
|
bool firstLineAdded = (added && length == 1) ||
|
|
|
|
(deleted && length == 0);
|
|
|
|
|
|
|
|
if (scn.linesAdded != 0) {
|
|
|
|
emit linesAdded(scn.linesAdded);
|
|
|
|
} else if (firstLineAdded) {
|
|
|
|
emit linesAdded(added ? 1 : -1);
|
|
|
|
}
|
|
|
|
|
2022-05-25 20:16:39 +00:00
|
|
|
const QByteArray bytes = QByteArray::fromRawData(scn.text, scn.text ? scn.length : 0);
|
2013-08-28 00:44:27 +00:00
|
|
|
emit modified(scn.modificationType, scn.position, scn.length,
|
|
|
|
scn.linesAdded, bytes, scn.line,
|
|
|
|
scn.foldLevelNow, scn.foldLevelPrev);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
case Notification::MacroRecord:
|
2013-08-28 00:44:27 +00:00
|
|
|
emit macroRecord(scn.message, scn.wParam, scn.lParam);
|
|
|
|
break;
|
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
case Notification::MarginClick:
|
2013-08-28 00:44:27 +00:00
|
|
|
emit marginClicked(scn.position, scn.modifiers, scn.margin);
|
|
|
|
break;
|
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
case Notification::NeedShown:
|
2013-08-28 00:44:27 +00:00
|
|
|
emit needShown(scn.position, scn.length);
|
|
|
|
break;
|
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
case Notification::Painted:
|
2013-08-28 00:44:27 +00:00
|
|
|
emit painted();
|
|
|
|
break;
|
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
case Notification::UserListSelection:
|
2013-08-28 00:44:27 +00:00
|
|
|
emit userListSelection();
|
|
|
|
break;
|
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
case Notification::URIDropped:
|
2019-05-04 18:14:48 +00:00
|
|
|
emit uriDropped(QString::fromUtf8(scn.text));
|
2013-08-28 00:44:27 +00:00
|
|
|
break;
|
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
case Notification::DwellStart:
|
2013-08-28 00:44:27 +00:00
|
|
|
emit dwellStart(scn.x, scn.y);
|
|
|
|
break;
|
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
case Notification::DwellEnd:
|
2013-08-28 00:44:27 +00:00
|
|
|
emit dwellEnd(scn.x, scn.y);
|
|
|
|
break;
|
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
case Notification::Zoom:
|
2013-08-28 00:44:27 +00:00
|
|
|
emit zoom(send(SCI_GETZOOM));
|
|
|
|
break;
|
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
case Notification::HotSpotClick:
|
2013-08-28 00:44:27 +00:00
|
|
|
emit hotSpotClick(scn.position, scn.modifiers);
|
|
|
|
break;
|
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
case Notification::HotSpotDoubleClick:
|
2013-08-28 00:44:27 +00:00
|
|
|
emit hotSpotDoubleClick(scn.position, scn.modifiers);
|
|
|
|
break;
|
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
case Notification::CallTipClick:
|
2013-08-28 00:44:27 +00:00
|
|
|
emit callTipClick();
|
|
|
|
break;
|
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
case Notification::AutoCSelection:
|
2013-08-28 00:44:27 +00:00
|
|
|
emit autoCompleteSelection(scn.lParam, QString::fromUtf8(scn.text));
|
|
|
|
break;
|
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
case Notification::AutoCCancelled:
|
2013-08-28 00:44:27 +00:00
|
|
|
emit autoCompleteCancelled();
|
|
|
|
break;
|
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
case Notification::FocusIn:
|
2019-05-04 18:14:48 +00:00
|
|
|
emit focusChanged(true);
|
|
|
|
break;
|
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
case Notification::FocusOut:
|
2019-05-04 18:14:48 +00:00
|
|
|
emit focusChanged(false);
|
|
|
|
break;
|
|
|
|
|
2013-08-28 00:44:27 +00:00
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScintillaEditBase::event_command(uptr_t wParam, sptr_t lParam)
|
|
|
|
{
|
|
|
|
emit command(wParam, lParam);
|
|
|
|
}
|
2019-05-04 18:14:48 +00:00
|
|
|
|
2022-01-04 23:07:50 +00:00
|
|
|
KeyMod ScintillaEditBase::ModifiersOfKeyboard()
|
2019-05-04 18:14:48 +00:00
|
|
|
{
|
|
|
|
const bool shift = QApplication::keyboardModifiers() & Qt::ShiftModifier;
|
|
|
|
const bool ctrl = QApplication::keyboardModifiers() & Qt::ControlModifier;
|
|
|
|
const bool alt = QApplication::keyboardModifiers() & Qt::AltModifier;
|
|
|
|
|
2022-08-27 07:35:52 +00:00
|
|
|
return ModifierFlags(shift, ctrl, alt);
|
2019-05-04 18:14:48 +00:00
|
|
|
}
|