// This module implements the portability layer for the TQt port of Scintilla. // // Copyright (c) 2006 // Riverbank Computing Limited // // 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. #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "Platform.h" #include "XPM.h" #include "qextscintillabase.h" // Type convertors. static TQFont *PFont(FontID id) { return reinterpret_cast(id); } static TQPainter *PSurface(SurfaceID id) { return reinterpret_cast(id); } static TQWidget *PWindow(WindowID id) { return reinterpret_cast(id); } static TQPopupMenu *PMenu(MenuID id) { return reinterpret_cast(id); } // Create a Point instance from a long value. Point Point::FromLong(long lpoint) { return Point(Platform::LowShortFromLong(lpoint), Platform::HighShortFromLong(lpoint)); } // Colour palette management. The TQt interface to colours means this class // doesn't have to do anything. Palette::Palette() { used = 0; allowRealization = false; } Palette::~Palette() { Release(); } void Palette::Release() { used = 0; } void Palette::WantFind(ColourPair &cp,bool want) { if (!want) cp.allocated.Set(cp.desired.AsLong()); } void Palette::Allocate(Window &) { } // Font management. Font::Font() : id(0) { } Font::~Font() { } void Font::Create(const char *faceName,int,int size,bool bold,bool italic,bool) { Release(); TQFont *f = new TQFont(); // If name of the font begins with a '-', assume, that it is an XLFD. if (faceName[0] == '-') f -> setRawName(faceName); else { f -> setFamily(faceName); f -> setPointSize(size); f -> setBold(bold); f -> setItalic(italic); } id = f; } void Font::Release() { if (id) { delete PFont(id); id = 0; } } // A surface abstracts a place to draw. class SurfaceImpl : public Surface { public: SurfaceImpl(); virtual ~SurfaceImpl(); void Init(WindowID); void Init(SurfaceID sid,WindowID); void InitPixMap(int width,int height,Surface *surface_,WindowID); void Release(); bool Initialised() {return painter;} void PenColour(ColourAllocated fore); int LogPixelsY() {return 72;} int DeviceHeightFont(int points) {return points;} void MoveTo(int x_,int y_) {painter -> moveTo(x_,y_);} void LineTo(int x_,int y_) {painter -> lineTo(x_,y_);} void Polygon(Point *pts,int npts,ColourAllocated fore, ColourAllocated back); void RectangleDraw(PRectangle rc,ColourAllocated fore, ColourAllocated back); void FillRectangle(PRectangle rc,ColourAllocated back); void FillRectangle(PRectangle rc,Surface &surfacePattern); void RoundedRectangle(PRectangle rc,ColourAllocated fore, ColourAllocated back); void AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill, ColourAllocated outline, int alphaOutline, int flags); void Ellipse(PRectangle rc,ColourAllocated fore,ColourAllocated back); void Copy(PRectangle rc,Point from,Surface &surfaceSource); void DrawTextNoClip(PRectangle rc,Font &font_,int ybase,const char *s, int len,ColourAllocated fore,ColourAllocated back); void DrawTextClipped(PRectangle rc,Font &font_,int ybase,const char *s, int len,ColourAllocated fore, ColourAllocated back); void DrawTextTransparent(PRectangle rc,Font &font_,int ybase, const char *s,int len,ColourAllocated fore); void MeasureWidths(Font &font_,const char *s,int len,int *positions); int WidthText(Font &font_,const char *s,int len); int WidthChar(Font &font_,char ch); int Ascent(Font &font_); int Descent(Font &font_); int InternalLeading(Font &font_) {return 0;} int ExternalLeading(Font &font_); int Height(Font &font_); int AverageCharWidth(Font &font_) {return WidthChar(font_,'n');} int SetPalette(Palette *,bool) {return 0;} void SetClip(PRectangle rc); void FlushCachedState() {painter -> flush();} void SetUnicodeMode(bool unicodeMode_) {unicodeMode = unicodeMode_;} void SetDBCSMode(int codePage) {} void DrawXPM(PRectangle rc,const XPM *xpm); private: void commonInit(TQPainter *painter_,bool mypainter_); bool setFont(Font &font_); TQString convertText(const char *s,int len); static TQRgb convertTQRgb(const ColourAllocated &col, unsigned alpha); static TQColor convertTQColor(const ColourAllocated &col, unsigned alpha = 0xff); bool unicodeMode; bool mypainter; TQPainter *painter; }; Surface *Surface::Allocate() { return new SurfaceImpl; } SurfaceImpl::SurfaceImpl() : unicodeMode(false), mypainter(false), painter(0) { } SurfaceImpl::~SurfaceImpl() { Release(); } void SurfaceImpl::commonInit(TQPainter *painter_,bool mypainter_) { Release(); painter = painter_; mypainter = mypainter_; } void SurfaceImpl::Init(WindowID) { commonInit(new TQPainter(new TQWidget()),true); } void SurfaceImpl::Init(SurfaceID sid,WindowID) { commonInit(PSurface(sid),false); } void SurfaceImpl::InitPixMap(int width,int height,Surface *,WindowID) { commonInit(new TQPainter(new TQPixmap(width,height)),true); } void SurfaceImpl::Release() { if (painter && mypainter) { TQPaintDevice *pd = painter -> device(); delete painter; delete pd; } painter = 0; } void SurfaceImpl::PenColour(ColourAllocated fore) { painter -> setPen(convertTQColor(fore)); } void SurfaceImpl::Polygon(Point *pts,int npts,ColourAllocated fore, ColourAllocated back) { TQPointArray qpts(npts); for (int i = 0; i < npts; ++i) qpts.setPoint(i,pts[i].x,pts[i].y); painter -> setPen(convertTQColor(fore)); painter -> setBrush(convertTQColor(back)); painter -> drawPolygon(qpts); } void SurfaceImpl::RectangleDraw(PRectangle rc,ColourAllocated fore, ColourAllocated back) { painter -> setPen(convertTQColor(fore)); painter -> setBrush(convertTQColor(back)); painter -> drawRect(rc.left,rc.top, rc.right - rc.left,rc.bottom - rc.top); } void SurfaceImpl::FillRectangle(PRectangle rc,ColourAllocated back) { painter -> setPen(TQt::NoPen); painter -> setBrush(convertTQColor(back)); painter -> drawRect(rc.left,rc.top, rc.right - rc.left,rc.bottom - rc.top); } void SurfaceImpl::FillRectangle(PRectangle rc,Surface &surfacePattern) { SurfaceImpl &si = static_cast(surfacePattern); TQPixmap *pm = static_cast(si.painter -> device()); if (pm) { TQBrush brsh(TQt::black,*pm); painter -> setPen(TQt::NoPen); painter -> setBrush(brsh); painter -> drawRect(rc.left,rc.top, rc.right - rc.left,rc.bottom - rc.top); } else FillRectangle(rc,ColourAllocated(0)); } void SurfaceImpl::RoundedRectangle(PRectangle rc,ColourAllocated fore, ColourAllocated back) { painter -> setPen(convertTQColor(fore)); painter -> setBrush(convertTQColor(back)); painter -> drawRoundRect(rc.left,rc.top, rc.right - rc.left,rc.bottom - rc.top); } void SurfaceImpl::AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill, ColourAllocated outline, int alphaOutline, int) { int w = rc.right - rc.left; int h = rc.bottom - rc.top; TQImage img(w, h, 32); img.fill(convertTQRgb(fill, alphaFill)); img.setAlphaBuffer(TRUE); // Assume that "cornerSize" means outline width. if (cornerSize > 0) { TQRgb oline = convertTQRgb(outline, alphaOutline); int linew = cornerSize; if (linew > w) linew = w; for (int y = 0; y < h; ++y) { int x; if (y < cornerSize || y >= (h - cornerSize)) for (x = 0; x < w; ++x) img.setPixel(x, y, oline); else { for (x = 0; x < linew; ++x) img.setPixel(x, y, oline); for (x = w - 1; x >= w - linew; --x) img.setPixel(x, y, oline); } } } painter->drawImage(rc.left, rc.top, img); } void SurfaceImpl::Ellipse(PRectangle rc,ColourAllocated fore, ColourAllocated back) { painter -> setPen(convertTQColor(fore)); painter -> setBrush(convertTQColor(back)); painter -> drawEllipse(rc.left,rc.top, rc.right - rc.left,rc.bottom - rc.top); } void SurfaceImpl::Copy(PRectangle rc,Point from,Surface &surfaceSource) { SurfaceImpl &si = static_cast(surfaceSource); TQPaintDevice *spd = si.painter -> device(); TQPaintDevice *dpd = painter -> device(); if (spd && dpd) { si.painter -> end(); painter -> end(); bitBlt(dpd,rc.left,rc.top,spd,from.x,from.y, rc.right - rc.left,rc.bottom - rc.top); si.painter -> begin(spd); painter -> begin(dpd); } } void SurfaceImpl::DrawTextNoClip(PRectangle rc,Font &font_,int ybase, const char *s,int len,ColourAllocated fore, ColourAllocated back) { FillRectangle(rc,back); DrawTextTransparent(rc,font_,ybase,s,len,fore); } void SurfaceImpl::DrawTextClipped(PRectangle rc,Font &font_,int ybase, const char *s,int len,ColourAllocated fore, ColourAllocated back) { SetClip(rc); DrawTextNoClip(rc,font_,ybase,s,len,fore,back); painter -> setClipping(FALSE); } void SurfaceImpl::DrawTextTransparent(PRectangle rc,Font &font_,int ybase, const char *s,int len, ColourAllocated fore) { TQString qs = convertText(s,len); setFont(font_); painter -> setPen(convertTQColor(fore)); painter -> drawText(rc.left,ybase,qs); } void SurfaceImpl::DrawXPM(PRectangle rc,const XPM *xpm) { int x, y; const TQPixmap &qpm = xpm -> Pixmap(); x = rc.left + (rc.Width() - qpm.width()) / 2; y = rc.top + (rc.Height() - qpm.height()) / 2; painter -> drawPixmap(x,y,qpm); } void SurfaceImpl::MeasureWidths(Font &font_,const char *s,int len, int *positions) { if (setFont(font_)) { int totalWidth = 0, ui = 0; TQString qs = convertText(s,len); TQFontMetrics fm = painter -> fontMetrics(); for (int i = 0; i < qs.length(); ++i) { totalWidth += fm.width(qs[i]); int l = (unicodeMode ? TQString(qs[i]).utf8().length() : 1); while (l--) positions[ui++] = totalWidth; } } else for (int i = 0; i < len; ++i) positions[i] = i + 1; } int SurfaceImpl::WidthText(Font &font_,const char *s,int len) { if (setFont(font_)) { TQString qs = convertText(s,len); return painter -> fontMetrics().width(qs,qs.length()); } return 1; } int SurfaceImpl::WidthChar(Font &font_,char ch) { if (setFont(font_)) return painter -> fontMetrics().width(ch); return 1; } int SurfaceImpl::Ascent(Font &font_) { if (setFont(font_)) return painter -> fontMetrics().ascent(); return 1; } int SurfaceImpl::Descent(Font &font_) { // TQt doesn't include the baseline in the descent, so add it. if (setFont(font_)) return painter -> fontMetrics().descent() + 1; return 1; } int SurfaceImpl::ExternalLeading(Font &font_) { if (setFont(font_)) return painter -> fontMetrics().leading(); return 0; } int SurfaceImpl::Height(Font &font_) { if (setFont(font_)) return painter -> fontMetrics().height(); return 1; } void SurfaceImpl::SetClip(PRectangle rc) { painter -> setClipRect(rc.left,rc.top, rc.right - rc.left,rc.bottom - rc.top); } // Set the painter font if there is one. Return true if it was set. bool SurfaceImpl::setFont(Font &font_) { TQFont *f = PFont(font_.GetID()); if (f) painter -> setFont(*f); return f; } // Convert a Scintilla string to a TQt Unicode string. TQString SurfaceImpl::convertText(const char *s,int len) { if (unicodeMode) return TQString::fromUtf8(s,len); TQString qs; qs.setLatin1(s,len); return qs; } // Convert a Scintilla colour and alpha component to a TQt TQRgb. TQRgb SurfaceImpl::convertTQRgb(const ColourAllocated &col, unsigned alpha) { long c = col.AsLong(); unsigned r = c & 0xff; unsigned g = (c >> 8) & 0xff; unsigned b = (c >> 16) & 0xff; TQRgb rgba = (alpha << 24) | (r << 16) | (g << 8) | b; return rgba; } // Convert a Scintilla colour, and optional alpha component, to a TQt TQColor. TQColor SurfaceImpl::convertTQColor(const ColourAllocated &col, unsigned alpha) { return TQColor(convertTQRgb(col, alpha)); } // Window (widget) management. Window::~Window() { } void Window::Destroy() { TQWidget *w = PWindow(id); if (w) { delete w; id = 0; } } bool Window::HasFocus() { return PWindow(id) -> hasFocus(); } PRectangle Window::GetPosition() { TQWidget *w = PWindow(id); // Before any size allocated pretend its big enough not to be scrolled. PRectangle rc(0,0,5000,5000); if (w) { const TQRect &r = w -> geometry(); rc.left = r.left(); rc.top = r.top(); rc.right = r.right() + 1; rc.bottom = r.bottom() + 1; } return rc; } void Window::SetPosition(PRectangle rc) { PWindow(id) -> setGeometry(rc.left,rc.top, rc.right - rc.left,rc.bottom - rc.top); } void Window::SetPositionRelative(PRectangle rc,Window relativeTo) { TQWidget *rel = PWindow(relativeTo.id); TQPoint pos = rel -> mapToGlobal(rel -> pos()); int x = pos.x() + rc.left; int y = pos.y() + rc.top; PWindow(id) -> setGeometry(x,y,rc.right - rc.left,rc.bottom - rc.top); } PRectangle Window::GetClientPosition() { return GetPosition(); } void Window::Show(bool show) { TQWidget *w = PWindow(id); if (show) w -> show(); else w -> hide(); } void Window::InvalidateAll() { TQWidget *w = PWindow(id); if (w) w -> update(); } void Window::InvalidateRectangle(PRectangle rc) { TQWidget *w = PWindow(id); if (w) w -> update(rc.left,rc.top, rc.right - rc.left,rc.bottom - rc.top); } void Window::SetFont(Font &font) { PWindow(id) -> setFont(*PFont(font.GetID())); } void Window::SetCursor(Cursor curs) { TQt::CursorShape qc; switch (curs) { case cursorText: qc = TQt::IbeamCursor; break; case cursorUp: qc = TQt::UpArrowCursor; break; case cursorWait: qc = TQt::WaitCursor; break; case cursorHoriz: qc = TQt::SizeHorCursor; break; case cursorVert: qc = TQt::SizeVerCursor; break; case cursorHand: qc = TQt::PointingHandCursor; break; default: qc = TQt::ArrowCursor; } PWindow(id) -> setCursor(qc); } void Window::SetTitle(const char *s) { PWindow(id) -> setCaption(s); } // Menu management. Menu::Menu() : id(0) { } void Menu::CreatePopUp() { Destroy(); id = new TQPopupMenu(); } void Menu::Destroy() { TQPopupMenu *m = PMenu(id); if (m) { delete m; id = 0; } } void Menu::Show(Point pt,Window &) { PMenu(id) -> popup(TQPoint(pt.x,pt.y)); } class DynamicLibraryImpl : public DynamicLibrary { public: DynamicLibraryImpl(const char *modulePath) { m = new TQLibrary(modulePath); m -> load(); } virtual ~DynamicLibraryImpl() { if (m) delete m; } virtual Function FindFunction(const char *name) { if (m) return m -> resolve(name); return 0; } virtual bool IsValid() { return m && m -> isLoaded(); } private: TQLibrary* m; }; DynamicLibrary *DynamicLibrary::Load(const char *modulePath) { return new DynamicLibraryImpl(modulePath); } // Elapsed time. This implementation assumes that the maximum elapsed time is // less than 48 hours. ElapsedTime::ElapsedTime() { TQTime now = TQTime::currentTime(); bigBit = now.hour() * 60 * 60 + now.minute() * 60 + now.second(); littleBit = now.msec(); } double ElapsedTime::Duration(bool reset) { long endBigBit, endLittleBit; TQTime now = TQTime::currentTime(); endBigBit = now.hour() * 60 * 60 + now.minute() * 60 + now.second(); endLittleBit = now.msec(); double duration = endBigBit - bigBit; if (duration < 0 || (duration == 0 && endLittleBit < littleBit)) duration += 24 * 60 * 60; duration += (endLittleBit - littleBit) / 1000.0; if (reset) { bigBit = endBigBit; littleBit = endLittleBit; } return duration; } // Manage system wide parameters. ColourDesired Platform::Chrome() { return ColourDesired(0xe0,0xe0,0xe0); } ColourDesired Platform::ChromeHighlight() { return ColourDesired(0xff,0xff,0xff); } const char *Platform::DefaultFont() { return TQApplication::font().family(); } int Platform::DefaultFontSize() { return TQApplication::font().pointSize(); } unsigned int Platform::DoubleClickTime() { return TQApplication::doubleClickInterval(); } bool Platform::MouseButtonBounce() { return true; } void Platform::DebugDisplay(const char *s) { qDebug("%s",s); } bool Platform::IsKeyDown(int) { return false; } long Platform::SendScintilla(WindowID w,unsigned int msg,unsigned long wParam, long lParam) { return static_cast(PWindow(w) -> parentWidget()) -> SendScintilla(msg,wParam,lParam); } long Platform::SendScintillaPointer(WindowID w,unsigned int msg, unsigned long wParam,void *lParam) { return static_cast(PWindow(w) -> parentWidget()) -> SendScintilla(msg,wParam,reinterpret_cast(lParam)); } bool Platform::IsDBCSLeadByte(int codepage,char ch) { // We don't support DBCS. return false; } int Platform::DBCSCharLength(int codePage,const char *s) { // We don't support DBCS. return 1; } int Platform::DBCSCharMaxLength() { // We don't support DBCS. return 2; } int Platform::Minimum(int a,int b) { return (a < b) ? a : b; } int Platform::Maximum(int a,int b) { return (a > b) ? a : b; } int Platform::Clamp(int val,int minVal,int maxVal) { if (val > maxVal) val = maxVal; if (val < minVal) val = minVal; return val; } //#define TRACE #ifdef TRACE void Platform::DebugPrintf(const char *format, ...) { char buffer[2000]; va_list pArguments; va_start(pArguments,format); vsprintf(buffer,format,pArguments); va_end(pArguments); DebugDisplay(buffer); } #else void Platform::DebugPrintf(const char *, ...) { } #endif static bool assertionPopUps = true; bool Platform::ShowAssertionPopUps(bool assertionPopUps_) { bool ret = assertionPopUps; assertionPopUps = assertionPopUps_; return ret; } void Platform::Assert(const char *c,const char *file,int line) { qFatal("Assertion [%s] failed at %s %d\n",c,file,line); }