diff options
Diffstat (limited to 'tqt/ScintillaTQt.cpp')
-rw-r--r-- | tqt/ScintillaTQt.cpp | 695 |
1 files changed, 695 insertions, 0 deletions
diff --git a/tqt/ScintillaTQt.cpp b/tqt/ScintillaTQt.cpp new file mode 100644 index 0000000..249ca5f --- /dev/null +++ b/tqt/ScintillaTQt.cpp @@ -0,0 +1,695 @@ +// The implementation of the TQt specific subclass of ScintillaBase. +// +// Copyright (c) 2006 +// Riverbank Computing Limited <[email protected]> +// +// This file is part of TQScintilla. +// +// This copy of TQScintilla is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) any +// later version. +// +// TQScintilla is supplied in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +// details. +// +// You should have received a copy of the GNU General Public License along with +// TQScintilla; see the file LICENSE. If not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <tqapplication.h> +#include <tqscrollbar.h> +#include <tqpopupmenu.h> +#include <tqstring.h> +#include <tqtimer.h> +#include <tqclipboard.h> +#include <tqdragobject.h> +#include <tqpainter.h> + +#include "tqextscintillabase.h" +#include "ScintillaTQt.h" + + +// We want to use the Scintilla notification names as TQt signal names. +#undef SCEN_CHANGE +#undef SCN_AUTOCSELECTION +#undef SCN_CALLTIPCLICK +#undef SCN_CHARADDED +#undef SCN_DOUBLECLICK +#undef SCN_DWELLEND +#undef SCN_DWELLSTART +#undef SCN_HOTSPOTCLICK +#undef SCN_HOTSPOTDOUBLECLICK +#undef SCN_MACRORECORD +#undef SCN_MARGINCLICK +#undef SCN_MODIFIED +#undef SCN_MODIFYATTEMPTRO +#undef SCN_NEEDSHOWN +#undef SCN_PAINTED +#undef SCN_SAVEPOINTLEFT +#undef SCN_SAVEPOINTREACHED +#undef SCN_STYLENEEDED +#undef SCN_UPDATEUI +#undef SCN_USERLISTSELECTION +#undef SCN_ZOOM + +enum +{ + SCEN_CHANGE = 768, + SCN_AUTOCSELECTION = 2022, + SCN_CALLTIPCLICK = 2021, + SCN_CHARADDED = 2001, + SCN_DOUBLECLICK = 2006, + SCN_DWELLEND = 2017, + SCN_DWELLSTART = 2016, + SCN_HOTSPOTCLICK = 2019, + SCN_HOTSPOTDOUBLECLICK = 2020, + SCN_MACRORECORD = 2009, + SCN_MARGINCLICK = 2010, + SCN_MODIFIED = 2008, + SCN_MODIFYATTEMPTRO = 2004, + SCN_NEEDSHOWN = 2011, + SCN_PAINTED = 2013, + SCN_SAVEPOINTLEFT = 2003, + SCN_SAVEPOINTREACHED = 2002, + SCN_STYLENEEDED = 2000, + SCN_UPDATEUI = 2007, + SCN_USERLISTSELECTION = 2014, + SCN_ZOOM = 2018 +}; + + +// The ctor. +ScintillaTQt::ScintillaTQt(TQextScintillaBase *tqsb_) : + capturedMouse(false), tqsb(tqsb_) +{ + wMain = tqsb -> txtarea; + + // We aren't a TQObject so we use the API class to do TQObject related + // things for us. + tqsb -> connect(&qtimer,TQT_SIGNAL(timeout()),TQT_SLOT(handleTimer())); + + Initialise(); +} + + +// The dtor. +ScintillaTQt::~ScintillaTQt() +{ + Finalise(); +} + + +// Initialise the instance. +void ScintillaTQt::Initialise() +{ + SetTicking(true); +} + + +// Tidy up the instance. +void ScintillaTQt::Finalise() +{ + SetTicking(false); + ScintillaBase::Finalise(); +} + + +// Start a drag. +void ScintillaTQt::StartDrag() +{ + // Allow applications to re-implement the drag start. + tqsb -> startDrag(); +} + + +// Do the real drag start. +void ScintillaTQt::StartDragImpl() +{ + TQDragObject *dobj = new TQTextDrag(textRange(&drag),tqsb -> txtarea); + + // Remove the dragged text if it was a move to another widget or + // application. + if (dobj -> drag() && dobj -> target() != tqsb -> txtarea) + ClearSelection(); + + inDragDrop = false; + SetDragPosition(invalidPosition); +} + + +// Handle a drag enter event. +void ScintillaTQt::dragEnterEvent(TQDragEnterEvent *dee) +{ + dragMoveEvent(dee); +} + + +// Handle a drag move event. +void ScintillaTQt::dragMoveEvent(TQDragMoveEvent *dme) +{ + dme -> acceptAction(TQTextDrag::canDecode(dme)); + SetDragPosition(PositionFromLocation(Point(dme -> pos().x(),dme -> pos().y()))); +} + + +// Handle a drag leave event. +void ScintillaTQt::dragLeaveEvent(TQDragLeaveEvent *dle) +{ + SetDragPosition(invalidPosition); +} + + +// Handle a drop event. +void ScintillaTQt::dropEvent(TQDropEvent *de) +{ + TQString text; + + if (TQTextDrag::decode(de,text)) + { + bool moving = (de -> source() == tqsb -> txtarea && de -> action() == TQDropEvent::Move); + + de -> acceptAction(); + + const char *s; + TQCString us; + + if (IsUnicodeMode()) + { + us = text.utf8(); + s = us.data(); + } + else + s = text.latin1(); + + DropAt(posDrop,s,moving,false); + SetDragPosition(invalidPosition); + Redraw(); + } +} + + +// Re-implement to trap certain messages. +sptr_t ScintillaTQt::WndProc(unsigned int iMessage,uptr_t wParam,sptr_t lParam) +{ + switch (iMessage) + { + case SCI_GRABFOCUS: + PWindow(wMain) -> setFocus(); + return 0; + + case SCI_GETDIRECTFUNCTION: + return reinterpret_cast<sptr_t>(DirectFunction); + + case SCI_GETDIRECTPOINTER: + return reinterpret_cast<sptr_t>(this); + } + + return ScintillaBase::WndProc(iMessage,wParam,lParam); +} + + +// Windows nonsense. +sptr_t ScintillaTQt::DefWndProc(unsigned int,uptr_t,sptr_t) +{ + return 0; +} + + +// Manage the timer. +void ScintillaTQt::SetTicking(bool on) +{ + if (timer.ticking != on) + { + timer.ticking = on; + + if (timer.ticking) + qtimer.start(timer.tickSize); + else + qtimer.stop(); + } + + timer.ticksToWait = caret.period; +} + + +// Grab or release the mouse (and keyboard). +void ScintillaTQt::SetMouseCapture(bool on) +{ + if (mouseDownCaptures) + if (on) + PWindow(wMain) -> grabMouse(); + else + PWindow(wMain) -> releaseMouse(); + + capturedMouse = on; +} + + +// Return true if the mouse/keyboard are currently grabbed. +bool ScintillaTQt::HaveMouseCapture() +{ + return capturedMouse; +} + + +// Set the position of the vertical scrollbar. +void ScintillaTQt::SetVerticalScrollPos() +{ + tqsb -> vsb -> setValue(topLine); +} + + +// Set the position of the horizontal scrollbar. +void ScintillaTQt::SetHorizontalScrollPos() +{ + tqsb -> hsb -> setValue(xOffset); +} + + +// Set the extent of the vertical and horizontal scrollbars and return true if +// the view needs re-drawing. +bool ScintillaTQt::ModifyScrollBars(int nMax,int nPage) +{ + tqsb -> vsb -> setMinValue(0); + tqsb -> vsb -> setMaxValue(nMax - nPage + 1); + tqsb -> vsb -> setLineStep(1); + tqsb -> vsb -> setPageStep(nPage); + + tqsb -> hsb -> setMinValue(0); + tqsb -> hsb -> setMaxValue(scrollWidth); + tqsb -> hsb -> setPageStep(scrollWidth / 10); + + return true; +} + + +// Called after SCI_SETWRAPMODE and SCI_SETHSCROLLBAR. +void ScintillaTQt::ReconfigureScrollBars() +{ + // Hide or show the scrollbars if needed. + if (horizontalScrollBarVisible && wrapState == eWrapNone) + tqsb->hsb->show(); + else + tqsb->hsb->hide(); + + if (verticalScrollBarVisible) + tqsb->vsb->show(); + else + tqsb->vsb->hide(); +} + + +// Notify interested parties of any change in the document. +void ScintillaTQt::NotifyChange() +{ + emit tqsb -> SCEN_CHANGE(); +} + + +// Notify interested parties of various events. This is the main mapping +// between Scintilla notifications and TQt signals. +void ScintillaTQt::NotifyParent(SCNotification scn) +{ + switch (scn.nmhdr.code) + { + case SCN_CALLTIPCLICK: + emit tqsb -> SCN_CALLTIPCLICK(scn.position); + break; + + case SCN_AUTOCSELECTION: + emit tqsb -> SCN_AUTOCSELECTION(scn.text,scn.lParam); + break; + + case SCN_CHARADDED: + emit tqsb -> SCN_CHARADDED(scn.ch); + break; + + case SCN_DOUBLECLICK: + emit tqsb -> SCN_DOUBLECLICK(); + break; + + case SCN_DWELLEND: + emit tqsb -> SCN_DWELLEND(scn.position,scn.x,scn.y); + break; + + case SCN_DWELLSTART: + emit tqsb -> SCN_DWELLSTART(scn.position,scn.x,scn.y); + break; + + case SCN_HOTSPOTCLICK: + emit tqsb -> SCN_HOTSPOTCLICK(scn.position,scn.modifiers); + break; + + case SCN_HOTSPOTDOUBLECLICK: + emit tqsb -> SCN_HOTSPOTDOUBLECLICK(scn.position,scn.modifiers); + break; + + case SCN_MACRORECORD: + emit tqsb -> SCN_MACRORECORD(scn.message,scn.wParam,scn.lParam); + break; + + case SCN_MARGINCLICK: + emit tqsb -> SCN_MARGINCLICK(scn.position,scn.modifiers, + scn.margin); + break; + + case SCN_MODIFIED: + emit tqsb -> SCN_MODIFIED(scn.position,scn.modificationType, + scn.text,scn.length,scn.linesAdded, + scn.line,scn.foldLevelNow, + scn.foldLevelPrev); + break; + + case SCN_MODIFYATTEMPTRO: + emit tqsb -> SCN_MODIFYATTEMPTRO(); + break; + + case SCN_NEEDSHOWN: + emit tqsb -> SCN_NEEDSHOWN(scn.position,scn.length); + break; + + case SCN_PAINTED: + emit tqsb -> SCN_PAINTED(); + break; + + case SCN_SAVEPOINTLEFT: + emit tqsb -> SCN_SAVEPOINTLEFT(); + break; + + case SCN_SAVEPOINTREACHED: + emit tqsb -> SCN_SAVEPOINTREACHED(); + break; + + case SCN_STYLENEEDED: + emit tqsb -> SCN_STYLENEEDED(scn.position); + break; + + case SCN_UPDATEUI: + emit tqsb -> SCN_UPDATEUI(); + break; + + case SCN_USERLISTSELECTION: + emit tqsb -> SCN_USERLISTSELECTION(scn.text,scn.wParam); + break; + + case SCN_ZOOM: + emit tqsb -> SCN_ZOOM(); + break; + + default: + tqWarning("Unknown notification: %u",scn.nmhdr.code); + } +} + + +// Handle a key that hasn't been filtered out as a command key. Return 0 if we +// haven't handled it. +int ScintillaTQt::KeyDefault(int key,int modifiers) +{ + // On Windows Alt Gr is returned as Ctrl-Alt (on X11 it seems to be the + // Meta key). We therefore ignore that combination. +#if defined(Q_OS_WIN) + modifiers &= (SCI_CTRL | SCI_ALT); + + if (modifiers == SCI_CTRL || modifiers == SCI_ALT) + return 0; +#else + if (modifiers & (SCI_CTRL | SCI_ALT)) + return 0; +#endif + + AddChar(key); + + return 1; +} + + +// Convert a text range to a TQString. +TQString ScintillaTQt::textRange(const SelectionText *text) +{ + TQString qs; + + if (text -> s) + if (IsUnicodeMode()) + qs = TQString::fromUtf8(text -> s); + else + qs.setLatin1(text -> s); + + return qs; +} + + +// Copy the selected text to the clipboard. +void ScintillaTQt::CopyToClipboard(const SelectionText &selectedText) +{ + TQApplication::clipboard() -> setText(textRange(&selectedText)); +} + + +// Implement copy. +void ScintillaTQt::Copy() +{ + if (currentPos != anchor) + { + SelectionText text; + + CopySelectionRange(&text); + CopyToClipboard(text); + } +} + + +// Implement paste. +void ScintillaTQt::Paste() +{ + TQString str = TQApplication::clipboard() -> text(); + + if (str.isEmpty()) + return; + + pdoc -> BeginUndoAction(); + + ClearSelection(); + + int len; + + if (IsUnicodeMode()) + { + TQCString s = str.utf8(); + + len = s.length(); + + if (len) + pdoc -> InsertString(currentPos,s.data(),len); + } + else + { + const char *s = str.latin1(); + + len = (s ? strlen(s) : 0); + + if (len) + pdoc -> InsertString(currentPos,s,len); + } + + SetEmptySelection(currentPos + len); + + pdoc -> EndUndoAction(); + + NotifyChange(); + Redraw(); +} + + +// A simple TQWidget sub-class to implement a call tip. No need to bother with +// all the moc stuff. +class TQtCallTip : public TQWidget +{ +public: + TQtCallTip(TQWidget *parent,ScintillaTQt *sci_); + ~TQtCallTip(); + +protected: + void paintEvent(TQPaintEvent *); + void mousePressEvent(TQMouseEvent *me); + +private: + ScintillaTQt *sci; +}; + + +// Create a call tip. +TQtCallTip::TQtCallTip(TQWidget *parent,ScintillaTQt *sci_) : + TQWidget(parent,0,WType_Popup|WStyle_Customize|WStyle_NoBorder), sci(sci_) +{ + // Ensure that the main window keeps the focus (and the caret flashing) + // when this is displayed. + setFocusProxy(parent); +} + + +// Destroy a call tip. +TQtCallTip::~TQtCallTip() +{ + // Ensure that the main window doesn't receive a focus out event when + // this is destroyed. + setFocusProxy(0); +} + + +// Paint a call tip. +void TQtCallTip::paintEvent(TQPaintEvent *) +{ + Surface *surfaceWindow = Surface::Allocate(); + + if (surfaceWindow) + { + TQPainter p(this); + + surfaceWindow -> Init(&p,0); + sci -> ct.PaintCT(surfaceWindow); + surfaceWindow -> Release(); + + delete surfaceWindow; + } +} + + +// Handle a mouse press in a call tip. +void TQtCallTip::mousePressEvent(TQMouseEvent *me) +{ + Point pt; + + pt.x = me -> x(); + pt.y = me -> y(); + + sci -> ct.MouseClick(pt); + sci -> CallTipClick(); +} + + +// Create a call tip window. +void ScintillaTQt::CreateCallTipWindow(PRectangle rc) +{ + if (!ct.wCallTip.Created()) + ct.wCallTip = ct.wDraw = new TQtCallTip(tqsb,this); + + PWindow(ct.wCallTip) -> resize(rc.right - rc.left,rc.bottom - rc.top); + ct.wCallTip.Show(); +} + + +// Add an item to the right button menu. +void ScintillaTQt::AddToPopUp(const char *label,int cmd,bool enabled) +{ + TQPopupMenu *pm = static_cast<TQPopupMenu *>(popup.GetID()); + + if (label[0] != '\0') + { + TQString tr_label = tqApp -> translate("ContextMenu",label); + + pm -> insertItem(tr_label,tqsb,TQT_SLOT(handlePopUp(int)),0,cmd); + pm -> setItemEnabled(cmd,enabled); + } + else + pm -> insertSeparator(); +} + + +// Claim the selection. +void ScintillaTQt::ClaimSelection() +{ + bool isSel = (currentPos != anchor); + + if (isSel) + { + TQClipboard *cb = TQApplication::clipboard(); + + // If we support X11 style selection then make it available + // now. + if (cb -> supportsSelection()) + { + SelectionText text; + + CopySelectionRange(&text); + + if (text.s) + { + cb -> setSelectionMode(TRUE); + cb -> setText(text.s); + cb -> setSelectionMode(FALSE); + } + } + + primarySelection = true; + } + else + primarySelection = false; + + emit tqsb -> TQSCN_SELCHANGED(isSel); +} + + +// Unclaim the selection. +void ScintillaTQt::UnclaimSelection() +{ + if (primarySelection) + { + primarySelection = false; + tqsb -> txtarea -> update(); + } +} + + +// Implemented to provide compatibility with the Windows version. +sptr_t ScintillaTQt::DirectFunction(ScintillaTQt *sciThis,unsigned int iMessage, + uptr_t wParam,sptr_t lParam) +{ + return sciThis -> WndProc(iMessage,wParam,lParam); +} + + +// Draw the contents of the widget. +void ScintillaTQt::paintEvent(TQPaintEvent *pe) +{ + bool isUnicodeMode = (pdoc && pdoc -> dbcsCodePage == SC_CP_UTF8); + + paintState = painting; + + const TQRect &qr = pe -> rect(); + + rcPaint.left = qr.left(); + rcPaint.top = qr.top(); + rcPaint.right = qr.right() + 1; + rcPaint.bottom = qr.bottom() + 1; + + PRectangle rcText = GetTextRectangle(); + paintingAllText = rcPaint.Contains(rcText); + + Surface *sw = Surface::Allocate(); + + if (sw) + { + TQPainter painter(PWindow(wMain)); + + sw -> Init(&painter,0); + sw -> SetUnicodeMode(isUnicodeMode); + Paint(sw,rcPaint); + sw -> Release(); + delete sw; + + // If the painting area was insufficient to cover the new style + // or brace highlight positions then repaint the whole thing. + if (paintState == paintAbandoned) + PWindow(wMain) -> update(); + } + + paintState = notPainting; +} |