You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tqscintilla/qt/PlatQt.cpp

937 lines
18 KiB

// This module implements the portability layer for the TQt port of Scintilla.
//
// Copyright (c) 2006
// Riverbank Computing Limited <info@riverbankcomputing.co.uk>
//
// 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 <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <tqapplication.h>
#include <tqwidget.h>
#include <tqfont.h>
#include <tqpixmap.h>
#include <tqimage.h>
#include <tqstring.h>
#include <tqlistbox.h>
#include <tqpopupmenu.h>
#include <tqdatetime.h>
#include <tqpainter.h>
#include <tqcursor.h>
#include <tqlibrary.h>
#include "Platform.h"
#include "XPM.h"
#include "qextscintillabase.h"
// Type convertors.
static TQFont *PFont(FontID id)
{
return reinterpret_cast<TQFont *>(id);
}
static TQPainter *PSurface(SurfaceID id)
{
return reinterpret_cast<TQPainter *>(id);
}
static TQWidget *PWindow(WindowID id)
{
return reinterpret_cast<TQWidget *>(id);
}
static TQPopupMenu *PMenu(MenuID id)
{
return reinterpret_cast<TQPopupMenu *>(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<SurfaceImpl &>(surfacePattern);
TQPixmap *pm = static_cast<TQPixmap *>(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<SurfaceImpl &>(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)
{
tqDebug("%s",s);
}
bool Platform::IsKeyDown(int)
{
return false;
}
long Platform::SendScintilla(WindowID w,unsigned int msg,unsigned long wParam,
long lParam)
{
return static_cast<QextScintillaBase *>(PWindow(w) -> parentWidget()) -> SendScintilla(msg,wParam,lParam);
}
long Platform::SendScintillaPointer(WindowID w,unsigned int msg,
unsigned long wParam,void *lParam)
{
return static_cast<QextScintillaBase *>(PWindow(w) -> parentWidget()) -> SendScintilla(msg,wParam,reinterpret_cast<long>(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)
{
tqFatal("Assertion [%s] failed at %s %d\n",c,file,line);
}