1 /** FXScintilla source code edit control
2 *
3 * PlatFOX.cxx - implementation of platform facilities on the FOX toolkit
4 *
5 * Copyright 2001-2004 by Gilles Filippini <gilles.filippini@free.fr>
6 *
7 * Adapted from the Scintilla source PlatGTK.cxx
8 * Copyright 1998-2004 by Neil Hodgson <neilh@scintilla.org>
9 *
10 * ====================================================================
11 *
12 * This file is part of FXScintilla.
13 *
14 * FXScintilla is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License as published by
16 * the Free Software Foundation; either version 2.1 of the License, or
17 * (at your option) any later version.
18 *
19 * FXScintilla is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Lesser General Public License for more details.
23 *
24 * You should have received a copy of the GNU Lesser General Public License
25 * along with FXScintilla; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 **/
28
29 #include <string.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32
33 #if !defined(WIN32) || defined(__CYGWIN__)
34 # if defined(__CYGWIN__)
35 # include <windows.h>
36 # ifdef PIC
37 # define FOXDLL
38 # endif
39 # endif
40 # include <sys/time.h>
41 # include <fx.h>
42 # include <fxkeys.h>
43 # include <FXRootWindow.h>
44 #else
45 # if defined(__MINGW32__) && defined(PIC) && !defined(FOXDLL)
46 # define FOXDLL
47 # endif
48 # pragma warning (disable : 4786)
49 # include <time.h>
50 # include <windows.h>
51 # include <fx.h>
52 # include <fxkeys.h>
53 #endif // !defined(WIN32) || defined(__CYGWIN__)
54
55 #include <FX88591Codec.h>
56
57 #include "Platform.h"
58 #include "Scintilla.h"
59 #include "ScintillaWidget.h"
60
61 #include <map>
62 using namespace std;
63
64 // X has a 16 bit coordinate space, so stop drawing here to avoid wrapping
65 static const int maxCoordinate = 32000;
66
FromLong(long lpoint)67 Point Point::FromLong(long lpoint) {
68 return Point(
69 Platform::LowShortFromLong(lpoint),
70 Platform::HighShortFromLong(lpoint));
71 }
72
Palette()73 Palette::Palette() {
74 used = 0;
75 allowRealization = false;
76 visual = 0;
77 size = 100;
78 entries = new ColourPair[size];
79 }
80
~Palette()81 Palette::~Palette() {
82 Release();
83 delete []entries;
84 entries = 0;
85 }
86
Release()87 void Palette::Release() {
88 used = 0;
89 delete []entries;
90 size = 100;
91 entries = new ColourPair[size];
92 }
93
94 #if defined(FOX_1_7) && ((FOX_MAJOR>1)||(FOX_MINOR>7)||(FOX_LEVEL>25))
95 # define RGBSWAP(rgb) FXRGB(FXBLUEVAL(rgb),FXGREENVAL(rgb),FXREDVAL(rgb))
96 #else
97 # define RGBSWAP(rgb) (rgb)
98 #endif
99
100 // This method either adds a colour to the list of wanted colours (want==true)
101 // or retrieves the allocated colour back to the ColourPair.
102 // This is one method to make it easier to keep the code for wanting and retrieving in sync.
WantFind(ColourPair & cp,bool want)103 void Palette::WantFind(ColourPair &cp, bool want) {
104 if (want) {
105 for (int i=0; i < used; i++) {
106 if (entries[i].desired == cp.desired)
107 return;
108 }
109
110 if (used >= size) {
111 int sizeNew = size * 2;
112 ColourPair *entriesNew = new ColourPair[sizeNew];
113 for (int j=0; j<size; j++) {
114 entriesNew[j] = entries[j];
115 }
116 delete []entries;
117 entries = entriesNew;
118 size = sizeNew;
119 }
120 entries[used].desired = cp.desired;
121 entries[used].allocated.Set(RGBSWAP(cp.desired.AsLong()));
122 used++;
123 } else {
124 for (int i=0; i < used; i++) {
125 if (entries[i].desired == cp.desired) {
126 cp.allocated = entries[i].allocated;
127 return;
128 }
129 }
130 cp.allocated.Set(RGBSWAP(cp.desired.AsLong()));
131 }
132 }
133
Allocate(Window &)134 void Palette::Allocate(Window & /* w */) {
135 // <FIXME/>
136 }
137
Font()138 Font::Font() : fid(0) {}
139
~Font()140 Font::~Font() {}
141
142 #ifndef WIN32
143
Create(const char * faceName,int characterSet,int size,bool bold,bool italic,int)144 void Font::Create(const char *faceName, int characterSet,
145 int size, bool bold, bool italic, int) {
146 Release();
147 // If name of the font begins with a '-', assume, that it is
148 // a full fontspec.
149 if (faceName[0] == '-') {
150 fid = new FXFont(FXApp::instance(), faceName);
151 }
152 else {
153 fid = new FXFont(FXApp::instance(), faceName, size,
154 bold ? FXFont::Bold : FXFont::Normal ,
155 italic ? FXFont::Italic : FXFont::Straight,
156 characterSet);
157 }
158 if (!fid) {
159 // Font not available so substitute with the app default font.
160 fid = FXApp::instance()->getNormalFont();
161 }
162 if (fid)
163 fid->create();
164 }
165
166 #else // WIN32
167
CharacterSetCode(int characterSet)168 static int CharacterSetCode(int characterSet) {
169 switch (characterSet) {
170 case SC_CHARSET_ANSI:
171 return FONTENCODING_DEFAULT;
172 case SC_CHARSET_DEFAULT:
173 return FONTENCODING_DEFAULT;
174 case SC_CHARSET_BALTIC:
175 return FONTENCODING_BALTIC;
176 case SC_CHARSET_CHINESEBIG5:
177 return FONTENCODING_DEFAULT;
178 case SC_CHARSET_EASTEUROPE:
179 return FONTENCODING_EASTEUROPE;
180 case SC_CHARSET_GB2312:
181 return FONTENCODING_DEFAULT;
182 case SC_CHARSET_GREEK:
183 return FONTENCODING_GREEK;
184 case SC_CHARSET_HANGUL:
185 return FONTENCODING_DEFAULT;
186 case SC_CHARSET_MAC:
187 return FONTENCODING_DEFAULT;
188 case SC_CHARSET_OEM:
189 return FONTENCODING_DEFAULT;
190 case SC_CHARSET_RUSSIAN:
191 return FONTENCODING_RUSSIAN;
192 case SC_CHARSET_CYRILLIC:
193 return FONTENCODING_CYRILLIC;
194 case SC_CHARSET_SHIFTJIS:
195 return FONTENCODING_DEFAULT;
196 case SC_CHARSET_SYMBOL:
197 return FONTENCODING_DEFAULT;
198 case SC_CHARSET_TURKISH:
199 return FONTENCODING_TURKISH;
200 case SC_CHARSET_JOHAB:
201 return FONTENCODING_DEFAULT;
202 case SC_CHARSET_HEBREW:
203 return FONTENCODING_HEBREW;
204 case SC_CHARSET_ARABIC:
205 return FONTENCODING_ARABIC;
206 case SC_CHARSET_VIETNAMESE:
207 return FONTENCODING_CP1258; /// Windows Vietnam
208 case SC_CHARSET_THAI:
209 return FONTENCODING_THAI;
210 case SC_CHARSET_8859_15:
211 return FONTENCODING_ISO_8859_15;
212 default:
213 return FONTENCODING_DEFAULT;
214 }
215 }
216
Create(const char * faceName,int characterSet,int size,bool bold,bool italic,int)217 void Font::Create(const char *faceName, int characterSet,
218 int size, bool bold, bool italic, int) {
219 Release();
220 fid = new FXFont(FXApp::instance(), faceName, size,
221 bold ? FXFont::Bold : FXFont::Normal ,
222 italic ? FXFont::Italic : FXFont::Straight,
223 CharacterSetCode(characterSet));
224 if (!fid) {
225 // Font not available so substitute with the app default font.
226 fid = FXApp::instance()->getNormalFont();
227 }
228 if (fid)
229 fid->create();
230 }
231
232 #endif // WIN32
233
Release()234 void Font::Release() {
235 if (fid)
236 delete fid;
237 fid = 0;
238 }
239
240 // ====================================================================
241 // Surface
242 // ====================================================================
243
244 class SurfaceImpl : public Surface {
245 bool unicodeMode;
246 FXDrawable *drawable;
247 FXImage *ppixmap;
248 static SurfaceImpl *s_dc_owner;
249 FXDCWindow *_dc;
250 FXDCWindow *dc();
251 int x;
252 int y;
253 bool inited;
254 bool createdDC;
255 FX88591Codec asciiCodec;
256 FXString codecBuffer;
257 public:
258 SurfaceImpl();
259 virtual ~SurfaceImpl();
260
261 void Init(WindowID wid);
262 void Init(SurfaceID sid, WindowID wid);
263 void InitPixMap(int width, int height, Surface *surface_, WindowID wid);
264
265 void Release();
266 bool Initialised();
267 void PenColour(ColourAllocated fore);
268 void BackColour(ColourAllocated back);
269 int LogPixelsY();
270 int DeviceHeightFont(int points);
271 void MoveTo(int x_, int y_);
272 void LineTo(int x_, int y_);
273 void Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back);
274 void RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back);
275 void FillRectangle(PRectangle rc, ColourAllocated back);
276 void FillRectangle(PRectangle rc, Surface &surfacePattern);
277 void RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back);
278 void AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill,
279 ColourAllocated outline, int alphaOutline, int flags);
280 void Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back);
281 void Copy(PRectangle rc, Point from, Surface &surfaceSource);
282
283 void DrawTextBase(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore);
284 void DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
285 void DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
286 void DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore);
287 void MeasureWidths(Font &font_, const char *s, int len, int *positions);
288 int WidthText(Font &font_, const char *s, int len);
289 int WidthChar(Font &font_, char ch);
290 int Ascent(Font &font_);
291 int Descent(Font &font_);
292 int InternalLeading(Font &font_);
293 int ExternalLeading(Font &font_);
294 int Height(Font &font_);
295 int AverageCharWidth(Font &font_);
296
297 int SetPalette(Palette *pal, bool inBackGround);
298 void SetClip(PRectangle rc);
299 void FlushCachedState();
300
301 void SetUnicodeMode(bool unicodeMode_);
SetDBCSMode(int)302 virtual void SetDBCSMode(int /* codePage */) {}
303 virtual void DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage);
304 };
305
306 SurfaceImpl * SurfaceImpl::s_dc_owner = NULL;
307
SurfaceImpl()308 SurfaceImpl::SurfaceImpl() : unicodeMode(false), drawable(0), ppixmap(0), _dc(0),
309 x(0), y(0), inited(false) {}
310
311
~SurfaceImpl()312 SurfaceImpl::~SurfaceImpl() {
313 Release();
314 }
315
dc()316 FXDCWindow * SurfaceImpl::dc()
317 {
318 if (s_dc_owner != this) {
319 if (s_dc_owner) {
320 delete s_dc_owner->_dc;
321 s_dc_owner->_dc = NULL;
322 }
323 s_dc_owner = this;
324 _dc = (drawable) ? new FXDCWindow(drawable) : NULL;
325 // Ask for lines that do not paint the last pixel so is like Win32
326 if (_dc)
327 _dc->setLineCap(CAP_NOT_LAST);
328 }
329 return _dc;
330
331 }
332
Release()333 void SurfaceImpl::Release() {
334 drawable = 0;
335 if (_dc) {
336 delete _dc;
337 _dc = 0;
338 s_dc_owner = 0;
339 }
340 if (ppixmap)
341 delete ppixmap;
342 ppixmap = 0;
343 x = 0;
344 y = 0;
345 createdDC = false;
346 inited = false;
347 }
348
Initialised()349 bool SurfaceImpl::Initialised() {
350 return inited;
351 }
352
Init(WindowID)353 void SurfaceImpl::Init(WindowID) {
354 Release();
355 inited = true;
356 }
357
Init(SurfaceID sid,WindowID)358 void SurfaceImpl::Init(SurfaceID sid, WindowID) {
359 Release();
360 drawable = reinterpret_cast<FXDrawable *>(sid);
361 createdDC = true;
362 inited = true;
363 }
364
InitPixMap(int width,int height,Surface *,WindowID)365 void SurfaceImpl::InitPixMap(int width, int height, Surface*, WindowID) {
366 Release();
367 if (height > 0 && width > 0)
368 ppixmap = new FXImage(FXApp::instance(), NULL, 0, width, height);
369 else
370 ppixmap = NULL;
371 drawable = ppixmap;
372 if (drawable)
373 drawable->create();
374 createdDC = true;
375 inited = true;
376 }
377
PenColour(ColourAllocated fore)378 void SurfaceImpl::PenColour(ColourAllocated fore) {
379 if (dc()) {
380 ColourDesired cd(fore.AsLong());
381 _dc->setForeground(FXRGB(cd.GetRed(), cd.GetGreen(), cd.GetBlue()));
382 }
383 }
384
BackColour(ColourAllocated back)385 void SurfaceImpl::BackColour(ColourAllocated back) {
386 if (dc()) {
387 ColourDesired cd(back.AsLong());
388 _dc->setBackground(FXRGB(cd.GetRed(), cd.GetGreen(), cd.GetBlue()));
389 }
390 }
391
LogPixelsY()392 int SurfaceImpl::LogPixelsY() {
393 return 72;
394 }
395
DeviceHeightFont(int points)396 int SurfaceImpl::DeviceHeightFont(int points) {
397 int logPix = LogPixelsY();
398 return (points * logPix + logPix / 2) / 72;
399 }
400
MoveTo(int x_,int y_)401 void SurfaceImpl::MoveTo(int x_, int y_) {
402 x = x_;
403 y = y_;
404 }
405
LineTo(int x_,int y_)406 void SurfaceImpl::LineTo(int x_, int y_) {
407 if (dc()) {
408 _dc->drawLine(x, y, x_, y_);
409 }
410 x = x_;
411 y = y_;
412 }
413
Polygon(Point * pts,int npts,ColourAllocated fore,ColourAllocated back)414 void SurfaceImpl::Polygon(Point *pts, int npts, ColourAllocated fore,
415 ColourAllocated back) {
416 if (dc()) {
417 FXPoint gpts[20];
418 if (npts < static_cast<int>((sizeof(gpts)/sizeof(gpts[0])))) {
419 for (int i=0;i<npts;i++) {
420 gpts[i].x = pts[i].x;
421 gpts[i].y = pts[i].y;
422 }
423 gpts[npts].x = pts[0].x;
424 gpts[npts].y = pts[0].y;
425 PenColour(back);
426 _dc->fillPolygon(gpts, npts);
427 PenColour(fore);
428 _dc->drawLines(gpts, npts + 1);
429 }
430 }
431 }
432
RectangleDraw(PRectangle rc,ColourAllocated fore,ColourAllocated back)433 void SurfaceImpl::RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
434 if (dc()) {
435 PenColour(fore);
436 BackColour(back);
437 _dc->drawRectangle(rc.left, rc.top,
438 rc.right - rc.left + 1, rc.bottom - rc.top + 1);
439 }
440 }
441
FillRectangle(PRectangle rc,ColourAllocated back)442 void SurfaceImpl::FillRectangle(PRectangle rc, ColourAllocated back) {
443 if (dc() && (rc.left < maxCoordinate)) { // Protect against out of range
444 // GTK+ rectangles include their lower and right edges
445 rc.bottom--;
446 rc.right--;
447 PenColour(back);
448 _dc->fillRectangle(rc.left, rc.top,
449 rc.right - rc.left + 1, rc.bottom - rc.top + 1);
450 }
451 }
452
FillRectangle(PRectangle rc,Surface & surfacePattern)453 void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern) {
454 if (static_cast<SurfaceImpl &>(surfacePattern).drawable) {
455 if (dc()) {
456 // Tile pattern over rectangle
457 // Currently assumes 8x8 pattern
458 int widthPat = 8;
459 int heightPat = 8;
460 for (int xTile = rc.left; xTile < rc.right; xTile += widthPat) {
461 int widthx = (xTile + widthPat > rc.right) ? rc.right - xTile : widthPat;
462 for (int yTile = rc.top; yTile < rc.bottom; yTile += heightPat) {
463 int heighty = (yTile + heightPat > rc.bottom) ? rc.bottom - yTile : heightPat;
464 _dc->drawArea(static_cast<SurfaceImpl &>(surfacePattern).drawable,
465 0, 0,
466 widthx, heighty,
467 xTile, yTile);
468 }
469 }
470 }
471 } else {
472 // Something is wrong so try to show anyway
473 // Shows up black because colour not allocated
474 FillRectangle(rc, ColourAllocated(0));
475 }
476 }
477
RoundedRectangle(PRectangle rc,ColourAllocated fore,ColourAllocated back)478 void SurfaceImpl::RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
479 if (((rc.right - rc.left) > 4) && ((rc.bottom - rc.top) > 4)) {
480 // Approximate a round rect with some cut off corners
481 Point pts[] = {
482 Point(rc.left + 2, rc.top),
483 Point(rc.right - 2, rc.top),
484 Point(rc.right, rc.top + 2),
485 Point(rc.right, rc.bottom - 2),
486 Point(rc.right - 2, rc.bottom),
487 Point(rc.left + 2, rc.bottom),
488 Point(rc.left, rc.bottom - 2),
489 Point(rc.left, rc.top + 2),
490 };
491 Polygon(pts, sizeof(pts) / sizeof(pts[0]), fore, back);
492 } else {
493 RectangleDraw(rc, fore, back);
494 }
495 }
496
497 // Plot a point into a guint32 buffer symetrically to all 4 qudrants
AllFour(FXImage * image,int width,int height,int x,int y,FXColor color)498 static void AllFour(FXImage *image, int width, int height, int x, int y, FXColor color) {
499 image->setPixel(x, y, color);
500 image->setPixel(width-1-x, y, color);
501 image->setPixel(x, height-1-y, color);
502 image->setPixel(width-1-x, height-1-y, color);
503 }
504
GetRed(unsigned int co)505 static unsigned int GetRed(unsigned int co) {
506 return (co >> 16) & 0xff;
507 }
508
GetGreen(unsigned int co)509 static unsigned int GetGreen(unsigned int co) {
510 return (co >> 8) & 0xff;
511 }
512
GetBlue(unsigned int co)513 static unsigned int GetBlue(unsigned int co) {
514 return co & 0xff;
515 }
516
AlphaRectangle(PRectangle rc,int cornerSize,ColourAllocated fill,int alphaFill,ColourAllocated outline,int alphaOutline,int flags)517 void SurfaceImpl::AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill,
518 ColourAllocated outline, int alphaOutline, int flags) {
519 if (dc()) {
520 int width = rc.Width();
521 int height = rc.Height();
522 // Ensure not distorted too much by corners when small
523 cornerSize = Platform::Minimum(cornerSize, (Platform::Minimum(width, height) / 2) - 2);
524 // Make a 32 bit deep image
525 FXImage * image = new FXImage(FXApp::instance(), NULL, IMAGE_OWNED, width, height);
526
527 FXColor valEmpty = 0;
528 FXColor valFill = FXRGBA(GetRed(fill.AsLong()), GetGreen(fill.AsLong()), GetBlue(fill.AsLong()), alphaFill);
529 FXColor valOutline = FXRGBA(GetRed(outline.AsLong()), GetGreen(outline.AsLong()), GetBlue(outline.AsLong()), alphaOutline);
530 for (int pY=0; pY<height; pY++) {
531 for (int pX=0; pX<width; pX++) {
532 if ((pX==0) || (pX==width-1) || (pY == 0) || (pY == height-1)) {
533 image->setPixel(pX, pY, valOutline);
534 } else {
535 image->setPixel(pX, pY, valFill);
536 }
537 }
538 }
539 for (int c=0;c<cornerSize; c++) {
540 for (int pX=0;pX<c+1; pX++) {
541 AllFour(image, width, height, pX, c-pX, valEmpty);
542 }
543 }
544 for (int pX=1;pX<cornerSize; pX++) {
545 AllFour(image, width, height, pX, cornerSize-pX, valOutline);
546 }
547
548 // Draw with alpha
549 image->create();
550 _dc->drawImage(image, rc.left, rc.top);
551 }
552 }
553
554
Ellipse(PRectangle rc,ColourAllocated fore,ColourAllocated back)555 void SurfaceImpl::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
556 if (dc()) {
557 PenColour(back);
558 _dc->fillArc(rc.left, rc.top,
559 rc.right - rc.left, rc.bottom - rc.top,
560 0, 32767);
561 PenColour(fore);
562 _dc->drawArc(rc.left, rc.top,
563 rc.right - rc.left, rc.bottom - rc.top,
564 0, 32767);
565 }
566 }
567
Copy(PRectangle rc,Point from,Surface & surfaceSource)568 void SurfaceImpl::Copy(PRectangle rc, Point from, Surface &surfaceSource) {
569 if (dc() && static_cast<SurfaceImpl &>(surfaceSource).drawable) {
570 _dc->drawArea(static_cast<SurfaceImpl &>(surfaceSource).drawable,
571 from.x, from.y,
572 rc.right - rc.left, rc.bottom - rc.top ,
573 rc.left, rc.top);
574 }
575 }
576
DrawTextBase(PRectangle rc,Font & font_,int ybase,const char * s,int len,ColourAllocated fore)577 void SurfaceImpl::DrawTextBase(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore)
578 {
579 if (dc()) {
580 PenColour(fore);
581 _dc->setFont(font_.GetID());
582 const int segmentLength = 1000;
583 int xbase = rc.left;
584 if (codecBuffer.length()) { codecBuffer=FXString::null; }
585 if (!unicodeMode) { // Fox uses UTF8 for text drawing, so we must convert any extended ASCII first.
586 for (int p=0; p<len; p++) {
587 if ((FXuchar)(s[p])>126) {
588 codecBuffer.length(asciiCodec.mb2utflen(s,len));
589 asciiCodec.mb2utf(&(codecBuffer.at(0)),codecBuffer.length(),s,len);
590 len=codecBuffer.length();
591 break;
592 }
593 }
594 }
595 while ((len > 0) && (xbase < maxCoordinate)) {
596 int lenDraw = Platform::Minimum(len, segmentLength);
597 _dc->drawText(xbase, ybase, codecBuffer.length()?codecBuffer.text():s, lenDraw);
598 len -= lenDraw;
599 if (len > 0) {
600 xbase += font_.GetID()->getTextWidth(s, lenDraw);
601 }
602 s += lenDraw;
603 }
604 }
605 if (codecBuffer.length()) { codecBuffer=FXString::null; }
606 }
607
DrawTextNoClip(PRectangle rc,Font & font_,int ybase,const char * s,int len,ColourAllocated fore,ColourAllocated back)608 void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len,
609 ColourAllocated fore, ColourAllocated back) {
610 if (dc()) {
611 FillRectangle(rc, back);
612 DrawTextBase(rc, font_, ybase, s, len, fore);
613 }
614 }
615
616 // On GTK+, exactly same as DrawText NoClip
617 // <FIXME> what about FOX ? </FIXME>
DrawTextClipped(PRectangle rc,Font & font_,int ybase,const char * s,int len,ColourAllocated fore,ColourAllocated back)618 void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len,
619 ColourAllocated fore, ColourAllocated back) {
620 DrawTextNoClip(rc, font_, ybase, s, len, fore, back);
621 }
622
DrawTextTransparent(PRectangle rc,Font & font_,int ybase,const char * s,int len,ColourAllocated fore)623 void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len,
624 ColourAllocated fore) {
625 DrawTextBase(rc, font_, ybase, s, len, fore);
626 }
627
MeasureWidths(Font & font_,const char * s,int len,int * positions)628 void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positions) {
629 if (font_.GetID()) {
630 int totalWidth = 0;
631 if (unicodeMode) {
632 const char*p=s;
633 for (FXint i=0; i<len; i++) {
634 int cw=1; // number of bytes in this utf8 character
635 FXuchar c=*p;
636 if (c>127) { // no check for invalid bytes here, there's not much we could do about it anyway.
637 if ((c>=194) && (c<=223)) {
638 cw=2;
639 } else if (c<=239) {
640 cw=3;
641 } else if (c<=244) {
642 cw=4;
643 }
644 }
645 int width = font_.GetID()->getTextWidth(p, cw);
646 totalWidth += width;
647 positions[i] = totalWidth;
648 p+=cw; // this many bytes consumed
649 for (FXint j=1; j<cw; j++) { // assign the same position to each byte for multibyte chars
650 positions[i+1]=positions[i];
651 i++;
652 }
653 }
654 } else {
655 for (int i=0;i<len;i++) {
656 int default_width=font_.GetID()->getTextWidth("8", 1);
657 #ifdef WIN32 // The width of chars > #239 are incorrect on Win32, so use default.
658 int width = ((FXuchar)(s[i])<=239) ? font_.GetID()->getTextWidth(s + i, 1) : default_width;
659 #else
660 int width = font_.GetID()->getTextWidth(s + i, 1);
661 #endif
662 totalWidth += width?width:default_width;
663 positions[i] = totalWidth;
664 }
665 }
666 } else {
667 for (int i=0;i<len;i++) {
668 positions[i] = i + 1;
669 }
670 }
671 }
672
WidthText(Font & font_,const char * s,int len)673 int SurfaceImpl::WidthText(Font &font_, const char *s, int len) {
674 if (font_.GetID())
675 return font_.GetID()->getTextWidth(s, len);
676 else
677 return 1;
678 }
679
WidthChar(Font & font_,char ch)680 int SurfaceImpl::WidthChar(Font &font_, char ch) {
681 if (font_.GetID())
682 return font_.GetID()->getTextWidth(&ch, 1);
683 else
684 return 1;
685 }
686
Ascent(Font & font_)687 int SurfaceImpl::Ascent(Font &font_) {
688 if (!font_.GetID())
689 return 1;
690 return font_.GetID()->getFontAscent();
691 }
692
Descent(Font & font_)693 int SurfaceImpl::Descent(Font &font_) {
694 if (!font_.GetID())
695 return 1;
696 return font_.GetID()->getFontDescent();
697 }
698
InternalLeading(Font &)699 int SurfaceImpl::InternalLeading(Font &) {
700 return 0;
701 }
702
ExternalLeading(Font &)703 int SurfaceImpl::ExternalLeading(Font &) {
704 return 0;
705 }
706
Height(Font & font_)707 int SurfaceImpl::Height(Font &font_) {
708 if (!font_.GetID())
709 return 1;
710 return font_.GetID()->getFontHeight();
711 }
712
AverageCharWidth(Font & font_)713 int SurfaceImpl::AverageCharWidth(Font &font_) {
714 if (font_.GetID())
715 return font_.GetID()->getTextWidth("n", 1);
716 else
717 return 1;
718 }
719
SetPalette(Palette *,bool)720 int SurfaceImpl::SetPalette(Palette *, bool) {
721 // Handled in palette allocation for GTK so this does nothing
722 // <FIXME> What about FOX ? </FIXME>
723 return 0;
724 }
725
SetClip(PRectangle rc)726 void SurfaceImpl::SetClip(PRectangle rc) {
727 if (dc())
728 _dc->setClipRectangle(rc.left, rc.top,
729 rc.right - rc.left, rc.bottom - rc.top);
730 }
731
FlushCachedState()732 void SurfaceImpl::FlushCachedState() {}
733
SetUnicodeMode(bool unicodeMode_)734 void SurfaceImpl::SetUnicodeMode(bool unicodeMode_) {
735 unicodeMode=unicodeMode_;
736 }
737
Allocate()738 Surface *Surface::Allocate() {
739 return new SurfaceImpl;
740 }
741
DrawRGBAImage(PRectangle rc,int width,int height,const unsigned char * pixelsImage)742 void SurfaceImpl::DrawRGBAImage( PRectangle rc, int width, int height,
743 const unsigned char *pixelsImage) {
744
745 }
746
~Window()747 Window::~Window() {}
748
Destroy()749 void Window::Destroy() {
750 if (wid)
751 delete wid;
752 wid = 0;
753 }
754
HasFocus()755 bool Window::HasFocus() {
756 return wid->hasFocus();
757 }
758
GetPosition()759 PRectangle Window::GetPosition() {
760 // Before any size allocated pretend its 1000 wide so not scrolled
761 PRectangle rc(0, 0, 1000, 1000);
762 if (wid) {
763 rc.left = wid->getX();
764 rc.top = wid->getY();
765 rc.right = rc.left + wid->getWidth();
766 rc.bottom = rc.top + wid->getHeight();
767 }
768 return rc;
769 }
770
SetPosition(PRectangle rc)771 void Window::SetPosition(PRectangle rc) {
772 wid->position(rc.left, rc.top, rc.Width(), rc.Height());
773 }
774
775
SetPositionRelative(PRectangle rc,Window relativeTo)776 void Window::SetPositionRelative(PRectangle rc, Window relativeTo) {
777 int ox = relativeTo.GetID()->getX() + rc.left;
778 int oy = relativeTo.GetID()->getY() + rc.top;
779 if (ox < 0)
780 ox = 0;
781 if (oy < 0)
782 oy = 0;
783
784 /* do some corrections to fit into screen */
785 int sizex = rc.right - rc.left;
786 int sizey = rc.bottom - rc.top;
787 int screenWidth = FXApp::instance()->getRootWindow()->getDefaultWidth();
788 int screenHeight = FXApp::instance()->getRootWindow()->getDefaultHeight();
789 if (sizex > screenWidth)
790 ox = 0; /* the best we can do */
791 else if (ox + sizex > screenWidth)
792 ox = screenWidth - sizex;
793 if (oy + sizey > screenHeight)
794 oy = screenHeight - sizey;
795
796 wid->position(ox, oy, rc.Width(), rc.Height());
797 }
798
GetClientPosition()799 PRectangle Window::GetClientPosition() {
800 // On GTK+, the client position is the window position
801 return PRectangle(0, 0, (wid) ? wid->getWidth() - 1 : 1000, (wid) ? wid->getHeight() -1 : 1000);
802 }
803
Show(bool show)804 void Window::Show(bool show) {
805 if (show) {
806 wid->show();
807 wid->raise();
808 }
809 else
810 wid->hide();
811 }
812
InvalidateAll()813 void Window::InvalidateAll() {
814 if (wid) {
815 wid->update();
816 }
817 }
818
InvalidateRectangle(PRectangle rc)819 void Window::InvalidateRectangle(PRectangle rc) {
820 if (wid)
821 wid->update(rc.left, rc.top, rc.right - rc.left + 1, rc.bottom - rc.top + 1);
822 }
823
SetFont(Font &)824 void Window::SetFont(Font &) {
825 // TODO
826 }
827
SetCursor(Cursor curs)828 void Window::SetCursor(Cursor curs) {
829 // We don't set the cursor to same value numerous times under FOX because
830 // it stores the cursor in the window once it's set
831 if (curs == cursorLast)
832 return;
833 FXDefaultCursor cursorID;
834 cursorLast = curs;
835
836 switch (curs) {
837 case cursorText:
838 cursorID = DEF_TEXT_CURSOR;
839 break;
840 case cursorArrow:
841 cursorID = DEF_ARROW_CURSOR;
842 break;
843 case cursorUp:
844 cursorID = DEF_MOVE_CURSOR;
845 break;
846 case cursorWait:
847 cursorID = DEF_SWATCH_CURSOR;
848 break;
849 case cursorHand:
850 // <FIXME/> Should be a hand cursor...
851 cursorID = DEF_HAND_CURSOR; //JKP
852 // cursorID = DEF_CROSSHAIR_CURSOR;
853 break;
854 case cursorReverseArrow:
855 cursorID = DEF_RARROW_CURSOR;
856 break;
857 default:
858 cursorID = DEF_ARROW_CURSOR;
859 cursorLast = cursorArrow;
860 break;
861 }
862 wid->setDefaultCursor(wid->getApp()->getDefaultCursor(cursorID));
863 }
864
SetTitle(const char * s)865 void Window::SetTitle(const char *s) {
866 static_cast<FXTopWindow *>(wid)->setTitle(s);
867 }
868
869
870 /*** JKP: FIXME: Ugly and not tested !!! ***/
GetMonitorRect(Point pt)871 PRectangle Window::GetMonitorRect(Point pt) {
872 FXRootWindow *rootwin=wid->getApp()->getRootWindow(); //(id->getApp(),id->getVisual());
873 FXint xpos=wid->getX();
874 FXint ypos=wid->getY();
875 return PRectangle(-xpos, -ypos, (-xpos) + rootwin->getDefaultWidth(),
876 (-ypos) + rootwin->getDefaultHeight());
877 }
878
879 // ====================================================================
880 // ListBoxFox
881 // ====================================================================
882
883 class ListBoxFox : public ListBox
884 {
885 FXList * list;
886 map<int, FXXPMIcon *> * pixhash;
887 int desiredVisibleRows;
888 unsigned int maxItemCharacters;
889 unsigned int aveCharWidth;
890 public:
891 CallBackAction doubleClickAction;
892 void *doubleClickActionData;
893
ListBoxFox()894 ListBoxFox() : list(0), pixhash(NULL), desiredVisibleRows(5), maxItemCharacters(0),
895 doubleClickAction(NULL), doubleClickActionData(NULL) {
896 }
~ListBoxFox()897 virtual ~ListBoxFox() {
898 ClearRegisteredImages();
899 }
900 virtual void Show(bool show=true);
901 virtual void SetFont(Font &font);
902 virtual void Create(Window &parent, int ctrlID, Point location_, int lineHeight_, bool unicodeMode_);
903 virtual void SetAverageCharWidth(int width);
904 virtual void SetVisibleRows(int rows);
905 virtual int GetVisibleRows() const;
906 virtual PRectangle GetDesiredRect();
907 virtual int CaretFromEdge();
908 virtual void Clear();
909 virtual void Append(char *s, int type = -1);
910 virtual int Length();
911 virtual void Select(int n);
912 virtual int GetSelection();
913 virtual int Find(const char *prefix);
914 virtual void GetValue(int n, char *value, int len);
915 virtual void RegisterImage(int type, const char *xpm_data);
916 virtual void ClearRegisteredImages();
SetDoubleClickAction(CallBackAction action,void * data)917 virtual void SetDoubleClickAction(CallBackAction action, void *data) {
918 doubleClickAction = action;
919 doubleClickActionData = data;
920 }
921 virtual void SetList(const char* list, char separator, char typesep);
922 virtual void RegisterRGBAImage(int type, int width, int height, const unsigned char *pixelsImage);
923 };
924
925
sListSortFunction(const FXListItem * item1,const FXListItem * item2)926 static int sListSortFunction(const FXListItem* item1, const FXListItem* item2) {
927 return compare(item1->getText(), item2->getText());
928 }
929
930 class PopupListBox : public FXPopup
931 {
932 FXDECLARE(PopupListBox)
933 protected:
PopupListBox()934 PopupListBox() {}
935 protected:
936 ListBoxFox * listBox;
937 FXList * list;
938 public:
939 enum {
940 ID_LIST = FXPopup::ID_LAST,
941 ID_LAST,
942 };
943 public:
944 long onKeyPress(FXObject *, FXSelector, void *);
945 long onListKeyPress(FXObject *, FXSelector, void *);
946 long onDoubleClicked(FXObject *, FXSelector, void *);
947 public:
948 PopupListBox(FXComposite * p, ListBoxFox * lb);
getList()949 FXList * getList() { return list; }
setFocus()950 virtual void setFocus() {
951 FXPopup::setFocus();
952 list->grabKeyboard();
953 }
killFocus()954 virtual void killFocus() {
955 list->ungrabKeyboard();
956 FXPopup::killFocus();
957 }
958 };
959
960 FXDEFMAP(PopupListBox) PopupListBoxMap[]={
961 FXMAPFUNC(SEL_KEYPRESS, 0, PopupListBox::onKeyPress),
962 FXMAPFUNC(SEL_KEYPRESS, PopupListBox::ID_LIST, PopupListBox::onListKeyPress),
963 FXMAPFUNC(SEL_DOUBLECLICKED, 0, PopupListBox::onDoubleClicked),
964 };
965
FXIMPLEMENT(PopupListBox,FXPopup,PopupListBoxMap,ARRAYNUMBER (PopupListBoxMap))966 FXIMPLEMENT(PopupListBox,FXPopup,PopupListBoxMap,ARRAYNUMBER(PopupListBoxMap))
967
968 PopupListBox::PopupListBox(FXComposite * p, ListBoxFox * lb) : FXPopup(p), listBox(lb)
969 {
970 list = new FXList(this,
971 this, ID_LIST, LIST_BROWSESELECT|LAYOUT_FILL_X|LAYOUT_FILL_Y|SCROLLERS_TRACK|HSCROLLER_NEVER);
972 list->setSortFunc(sListSortFunction);
973 }
974
onKeyPress(FXObject * sender,FXSelector sel,void * ptr)975 long PopupListBox::onKeyPress(FXObject * sender, FXSelector sel, void * ptr)
976 {
977 return FXPopup::onKeyPress(sender, sel, ptr);
978 }
979
onListKeyPress(FXObject * sender,FXSelector sel,void * ptr)980 long PopupListBox::onListKeyPress(FXObject * sender, FXSelector sel, void * ptr)
981 {
982 list->setTarget(NULL);
983 list->onKeyPress(sender, sel, ptr);
984 FXEvent * event = (FXEvent *)ptr;
985
986 switch(event->code) {
987 case KEY_Page_Up:
988 case KEY_KP_Page_Up:
989 case KEY_Page_Down:
990 case KEY_KP_Page_Down:
991 case KEY_Up:
992 case KEY_KP_Up:
993 case KEY_Down:
994 case KEY_KP_Down:
995 case KEY_Home:
996 case KEY_KP_Home:
997 case KEY_End:
998 case KEY_KP_End:
999 break;
1000 default:
1001 getOwner()->handle(this, MKUINT(0, SEL_KEYPRESS), ptr);
1002 }
1003 list->setTarget(this);
1004 return 1;
1005 }
1006
onDoubleClicked(FXObject *,FXSelector,void *)1007 long PopupListBox::onDoubleClicked(FXObject *, FXSelector, void *)
1008 {
1009 if (listBox->doubleClickAction) {
1010 listBox->doubleClickAction(listBox->doubleClickActionData);
1011 }
1012 return 1;
1013 }
1014
1015 // ====================================================================
1016
Create(Window & parent,int,Point,int,bool)1017 void ListBoxFox::Create(Window & parent, int, Point, int, bool) {
1018 wid = new PopupListBox(static_cast<FXComposite *>(parent.GetID()), this);
1019 wid->create();
1020 list = (static_cast<PopupListBox *>(wid))->getList();
1021 }
1022
SetFont(Font & scint_font)1023 void ListBoxFox::SetFont(Font &scint_font) {
1024 list->setFont(scint_font.GetID());
1025 }
1026
SetAverageCharWidth(int width)1027 void ListBoxFox::SetAverageCharWidth(int width) {
1028 aveCharWidth = width;
1029 }
1030
SetVisibleRows(int rows)1031 void ListBoxFox::SetVisibleRows(int rows) {
1032 list->setNumVisible(rows);
1033 }
1034
GetVisibleRows() const1035 int ListBoxFox::GetVisibleRows() const {
1036 return list->getNumVisible();
1037 }
1038
GetDesiredRect()1039 PRectangle ListBoxFox::GetDesiredRect() {
1040 // Before any size allocated pretend its 100 wide so not scrolled
1041 PRectangle rc(0, 0, 100, 100);
1042 if (wid) {
1043 // Height
1044 int rows = Length();
1045 if ((rows == 0) || (rows > desiredVisibleRows))
1046 rows = desiredVisibleRows;
1047 list->setNumVisible(rows);
1048 rc.bottom = wid->getHeight();
1049 // Width
1050 int width = maxItemCharacters;
1051 if (width < 12)
1052 width = 12;
1053 rc.right = width * (aveCharWidth+aveCharWidth/3);
1054 if (Length() > rows)
1055 rc.right += list->verticalScrollBar()->getWidth();
1056
1057 // <FIXME/>
1058 /* int rows = Length();
1059 if ((rows == 0) || (rows > desiredVisibleRows))
1060 rows = desiredVisibleRows;
1061
1062 GtkRequisition req;
1063 int height;
1064
1065 // First calculate height of the clist for our desired visible row count otherwise it tries to expand to the total # of rows
1066 height = (rows * GTK_CLIST(list)->row_height
1067 + rows + 1
1068 + 2 * (list->style->klass->ythickness
1069 + GTK_CONTAINER(list)->border_width));
1070 gtk_widget_set_usize(GTK_WIDGET(list), -1, height);
1071
1072 // Get the size of the scroller because we set usize on the window
1073 gtk_widget_size_request(GTK_WIDGET(scroller), &req);
1074 rc.right = req.width;
1075 rc.bottom = req.height;
1076
1077 gtk_widget_set_usize(GTK_WIDGET(list), -1, -1);
1078 int width = maxItemCharacters;
1079 if (width < 12)
1080 width = 12;
1081 rc.right = width * (aveCharWidth+aveCharWidth/3);
1082 if (Length() > rows)
1083 rc.right = rc.right + 16;*/
1084 }
1085 return rc;
1086
1087 }
1088
Show(bool show)1089 void ListBoxFox::Show(bool show) {
1090 if (show) {
1091 (static_cast<FXPopup *>(wid))->popup(NULL, wid->getX(), wid->getY(),
1092 wid->getWidth(), wid->getHeight());
1093 list->selectItem(0);
1094 }
1095 }
1096
CaretFromEdge()1097 int ListBoxFox::CaretFromEdge() {
1098 // <FIXME/> return 4 + GetWidth();
1099 return 0;
1100 }
1101
Clear()1102 void ListBoxFox::Clear() {
1103 list->clearItems();
1104 maxItemCharacters = 0;
1105 }
1106
Append(char * s,int type)1107 void ListBoxFox::Append(char *s, int type) {
1108 FXXPMIcon * icon = NULL;
1109 if ((type >= 0) && pixhash) {
1110 map<int, FXXPMIcon *>::iterator it = pixhash->find(type);
1111 if (it != pixhash->end())
1112 icon = (*it).second;
1113 }
1114 list->appendItem(s, icon);
1115 size_t len = strlen(s);
1116 if (maxItemCharacters < len)
1117 maxItemCharacters = len;
1118 if (list->getNumItems() <= desiredVisibleRows)
1119 list->setNumVisible(list->getNumItems());
1120 list->sortItems();
1121 }
1122
Length()1123 int ListBoxFox::Length() {
1124 if (wid)
1125 return list->getNumItems();
1126 return 0;
1127 }
1128
Select(int n)1129 void ListBoxFox::Select(int n) {
1130 // Case n==-1 handled by FXList
1131 list->setCurrentItem(n, true);
1132 }
1133
GetSelection()1134 int ListBoxFox::GetSelection() {
1135 // Returns -1 when no current item
1136 return list->getCurrentItem();
1137 }
1138
Find(const char * prefix)1139 int ListBoxFox::Find(const char *prefix) {
1140 int count = Length();
1141 for (int i = 0; i < count; i++) {
1142 FXString text = list->getItemText(i);
1143 const char* s = text.text();
1144 if (s && (0 == strncmp(prefix, s, strlen(prefix)))) {
1145 return i;
1146 }
1147 }
1148 return - 1;
1149 }
1150
GetValue(int n,char * value,int len)1151 void ListBoxFox::GetValue(int n, char *value, int len) {
1152 FXString text = list->getItemText(n);
1153 if (text.length() && len > 0) {
1154 strncpy(value, text.text(), len);
1155 value[len - 1] = '\0';
1156 } else {
1157 value[0] = '\0';
1158 }
1159 }
1160
RegisterImage(int type,const char * xpm_data)1161 void ListBoxFox::RegisterImage(int type, const char *xpm_data)
1162 {
1163 FXXPMIcon * icon = new FXXPMIcon(FXApp::instance(), &xpm_data);
1164 icon->create();
1165 if (!pixhash)
1166 pixhash = new map<int, FXXPMIcon *>;
1167 FXXPMIcon * old = (*pixhash)[type];
1168 if (old)
1169 delete old;
1170 (*pixhash)[type] = icon;
1171 }
1172
ClearRegisteredImages()1173 void ListBoxFox::ClearRegisteredImages()
1174 {
1175 if (pixhash) {
1176 map<int, FXXPMIcon *>::iterator it;
1177 for (it = pixhash->begin(); it != pixhash->end(); it++) {
1178 delete (*it).second;
1179 }
1180 delete pixhash;
1181 }
1182 }
1183
SetList(const char * items,char separator,char typesep)1184 void ListBoxFox::SetList(const char* items, char separator, char typesep) {
1185 Clear();
1186 int count = strlen(items) + 1;
1187 char *words = new char[count];
1188 if (words) {
1189 memcpy(words, items, count);
1190 char *startword = words;
1191 char *numword = NULL;
1192 int i = 0;
1193 for (; words[i]; i++) {
1194 if (words[i] == separator) {
1195 words[i] = '\0';
1196 if (numword)
1197 *numword = '\0';
1198 Append(startword, numword?atoi(numword + 1):-1);
1199 startword = words + i + 1;
1200 numword = NULL;
1201 } else if (words[i] == typesep) {
1202 numword = words + i;
1203 }
1204 }
1205 if (startword) {
1206 if (numword)
1207 *numword = '\0';
1208 Append(startword, numword?atoi(numword + 1):-1);
1209 }
1210 delete []words;
1211 }
1212 }
1213
RegisterRGBAImage(int type,int width,int height,const unsigned char * pixelsImage)1214 void ListBoxFox::RegisterRGBAImage(int type, int width, int height, const unsigned char *pixelsImage) {
1215
1216 }
1217
1218
1219 // ====================================================================
1220 // ListBox
1221 // ====================================================================
1222
ListBox()1223 ListBox::ListBox()
1224 {
1225 }
1226
~ListBox()1227 ListBox::~ListBox()
1228 {
1229 }
1230
Allocate()1231 ListBox * ListBox::Allocate()
1232 {
1233 return new ListBoxFox();
1234 }
1235
1236
1237 // ====================================================================
1238 // Menu
1239 // ====================================================================
1240
Menu()1241 Menu::Menu() : mid(0) {}
1242
1243
CreatePopUp()1244 void Menu::CreatePopUp() {
1245 Destroy();
1246 mid = new FXMenuPane(FXApp::instance()->getCursorWindow());
1247 }
1248
Destroy()1249 void Menu::Destroy() {
1250 if (mid)
1251 delete mid;
1252 mid = 0;
1253 }
1254
Show(Point pt,Window &)1255 void Menu::Show(Point pt, Window &) {
1256 int screenHeight = FXApp::instance()->getRootWindow()->getDefaultHeight();
1257 int screenWidth = FXApp::instance()->getRootWindow()->getDefaultWidth();
1258 mid->create();
1259 if ((pt.x + mid->getWidth()) > screenWidth) {
1260 pt.x = screenWidth - mid->getWidth();
1261 }
1262 if ((pt.y + mid->getHeight()) > screenHeight) {
1263 pt.y = screenHeight - mid->getHeight();
1264 }
1265 mid->popup(NULL, pt.x - 4, pt.y);
1266 FXApp::instance()->runModalWhileShown(mid);
1267 }
1268
1269 #ifndef WIN32
1270
ElapsedTime()1271 ElapsedTime::ElapsedTime() {
1272 timeval curTime;
1273 gettimeofday(&curTime, NULL);
1274 bigBit = curTime.tv_sec;
1275 littleBit = curTime.tv_usec;
1276 }
1277
Duration(bool reset)1278 double ElapsedTime::Duration(bool reset) {
1279 timeval curTime;
1280 gettimeofday(&curTime, NULL);
1281 long endBigBit = curTime.tv_sec;
1282 long endLittleBit = curTime.tv_usec;
1283 double result = 1000000.0 * (endBigBit - bigBit);
1284 result += endLittleBit - littleBit;
1285 result /= 1000000.0;
1286 if (reset) {
1287 bigBit = endBigBit;
1288 littleBit = endLittleBit;
1289 }
1290 return result;
1291 }
1292
1293 #else // WIN32
1294
1295 static bool initialisedET = false;
1296 static bool usePerformanceCounter = false;
1297 static LARGE_INTEGER frequency;
1298
ElapsedTime()1299 ElapsedTime::ElapsedTime() {
1300 if (!initialisedET) {
1301 usePerformanceCounter = ::QueryPerformanceFrequency(&frequency);
1302 initialisedET = true;
1303 }
1304 if (usePerformanceCounter) {
1305 LARGE_INTEGER timeVal;
1306 ::QueryPerformanceCounter(&timeVal);
1307 bigBit = timeVal.HighPart;
1308 littleBit = timeVal.LowPart;
1309 } else {
1310 bigBit = clock();
1311 }
1312 }
1313
Duration(bool reset)1314 double ElapsedTime::Duration(bool reset) {
1315 double result;
1316 long endBigBit;
1317 long endLittleBit;
1318
1319 if (usePerformanceCounter) {
1320 LARGE_INTEGER lEnd;
1321 ::QueryPerformanceCounter(&lEnd);
1322 endBigBit = lEnd.HighPart;
1323 endLittleBit = lEnd.LowPart;
1324 LARGE_INTEGER lBegin;
1325 lBegin.HighPart = bigBit;
1326 lBegin.LowPart = littleBit;
1327 double elapsed = lEnd.QuadPart - lBegin.QuadPart;
1328 result = elapsed / static_cast<double>(frequency.QuadPart);
1329 } else {
1330 endBigBit = clock();
1331 endLittleBit = 0;
1332 double elapsed = endBigBit - bigBit;
1333 result = elapsed / CLOCKS_PER_SEC;
1334 }
1335 if (reset) {
1336 bigBit = endBigBit;
1337 littleBit = endLittleBit;
1338 }
1339 return result;
1340 }
1341 #endif // WIN32
1342
1343 // ====================================================================
1344 // Dynamic library handling.
1345 // - fxdllXxx API with Fox >= 1.2
1346 // ====================================================================
1347
1348 // Fox >= 1.2 has dynamic librarie handling
1349
1350
1351 #include <FXDLL.h>
1352
1353 #ifdef FOX_1_6
1354 class DynamicLibraryImpl : public DynamicLibrary {
1355 protected:
1356 void * m;
1357 public:
DynamicLibraryImpl(const char * modulePath)1358 DynamicLibraryImpl(const char *modulePath) {
1359 m = fxdllOpen(modulePath);
1360 }
1361
~DynamicLibraryImpl()1362 virtual ~DynamicLibraryImpl() {
1363 if (m != NULL)
1364 fxdllClose(m);
1365 }
1366
1367 // Use lt_dlsym to get a pointer to the relevant function.
FindFunction(const char * name)1368 virtual Function FindFunction(const char *name) {
1369 if (m != NULL) {
1370 return fxdllSymbol(m, name);
1371 } else
1372 return NULL;
1373 }
1374
IsValid()1375 virtual bool IsValid() {
1376 return m != NULL;
1377 }
1378 };
1379 #else
1380 class DynamicLibraryImpl : public DynamicLibrary {
1381 protected:
1382 FXDLL*dll;
1383 public:
DynamicLibraryImpl(const char * modulePath)1384 DynamicLibraryImpl(const char *modulePath) {
1385 dll=new FXDLL();
1386 dll->load(modulePath);
1387 }
1388
~DynamicLibraryImpl()1389 virtual ~DynamicLibraryImpl() {
1390 dll->unload();
1391 delete dll;
1392 }
1393
1394
1395 // Use lt_dlsym to get a pointer to the relevant function.
FindFunction(const char * name)1396 virtual Function FindFunction(const char *name) {
1397 if (dll->loaded()) {
1398 return dll->address(name);
1399 } else
1400 return NULL;
1401 }
1402
IsValid()1403 virtual bool IsValid() {
1404 return dll->loaded();
1405 }
1406 };
1407 #endif
1408
1409
Load(const char * modulePath)1410 DynamicLibrary *DynamicLibrary::Load(const char *modulePath) {
1411 return static_cast<DynamicLibrary *>( new DynamicLibraryImpl(modulePath) );
1412 }
1413
1414
1415 // ====================================================================
1416 // Platform
1417 // ====================================================================
1418
Chrome()1419 ColourDesired Platform::Chrome() {
1420 return ColourDesired(0xe0, 0xe0, 0xe0);
1421 }
1422
ChromeHighlight()1423 ColourDesired Platform::ChromeHighlight() {
1424 return ColourDesired(0xff, 0xff, 0xff);
1425 }
1426
DefaultFont()1427 const char *Platform::DefaultFont() {
1428 static FXString fontName;
1429 fontName = FXApp::instance()->getNormalFont()->getName();
1430 return fontName.text();
1431 }
1432
DefaultFontSize()1433 int Platform::DefaultFontSize() {
1434 // Warning: FOX gives the font size in deci-point
1435 return FXApp::instance()->getNormalFont()->getSize() / 10;
1436 }
1437
DoubleClickTime()1438 unsigned int Platform::DoubleClickTime() {
1439 return 500; // Half a second
1440 }
1441
MouseButtonBounce()1442 bool Platform::MouseButtonBounce() {
1443 return true; // <FIXME/> same as gtk?
1444 }
1445
DebugDisplay(const char * s)1446 void Platform::DebugDisplay(const char *s) {
1447 printf("%s", s);
1448 }
1449
IsKeyDown(int)1450 bool Platform::IsKeyDown(int) {
1451 // TODO: discover state of keys in GTK+/X
1452 return false;
1453 }
1454
1455 /* These methods are now implemented in ScintillaFOX.cxx
1456 long Platform::SendScintilla(WindowID w, unsigned int msg,
1457 unsigned long wParam, long lParam) {
1458 return static_cast<FXScintilla *>(w)->sendMessage(msg, wParam, lParam);
1459 }
1460 long Platform::SendScintillaPointer(WindowID w, unsigned int msg,
1461 unsigned long wParam, void *lParam) {
1462 return static_cast<FXScintilla *>(w)->
1463 sendMessage(msg, wParam, reinterpret_cast<sptr_t>(lParam));
1464 }
1465 */
1466
IsDBCSLeadByte(int,char)1467 bool Platform::IsDBCSLeadByte(int /*codePage*/, char /*ch*/) {
1468 return false;
1469 }
1470
DBCSCharLength(int,const char * s)1471 int Platform::DBCSCharLength(int /*codePage*/, const char *s) {
1472 int bytes = mblen(s, MB_CUR_MAX);
1473 if (bytes >= 1)
1474 return bytes;
1475 else
1476 return 1;
1477 }
1478
DBCSCharMaxLength()1479 int Platform::DBCSCharMaxLength() {
1480 return MB_CUR_MAX;
1481 }
1482
1483 // These are utility functions not really tied to a platform
1484
Minimum(int a,int b)1485 int Platform::Minimum(int a, int b) {
1486 if (a < b)
1487 return a;
1488 else
1489 return b;
1490 }
1491
Maximum(int a,int b)1492 int Platform::Maximum(int a, int b) {
1493 if (a > b)
1494 return a;
1495 else
1496 return b;
1497 }
1498
1499 //#define TRACE
1500
1501 #ifdef TRACE
DebugPrintf(const char * format,...)1502 void Platform::DebugPrintf(const char *format, ...) {
1503 char buffer[2000];
1504 va_list pArguments;
1505 va_start(pArguments, format);
1506 vsprintf(buffer, format, pArguments);
1507 va_end(pArguments);
1508 Platform::DebugDisplay(buffer);
1509 }
1510 #else
DebugPrintf(const char *,...)1511 void Platform::DebugPrintf(const char *, ...) {
1512 }
1513 #endif
1514
1515 // Not supported for GTK+
1516 static bool assertionPopUps = true;
1517
ShowAssertionPopUps(bool assertionPopUps_)1518 bool Platform::ShowAssertionPopUps(bool assertionPopUps_) {
1519 bool ret = assertionPopUps;
1520 assertionPopUps = assertionPopUps_;
1521 return ret;
1522 }
1523
Assert(const char * c,const char * file,int line)1524 void Platform::Assert(const char *c, const char *file, int line) {
1525 char buffer[2000];
1526 sprintf(buffer, "Assertion [%s] failed at %s %d", c, file, line);
1527 strcat(buffer, "\r\n");
1528 Platform::DebugDisplay(buffer);
1529 abort();
1530 }
1531
Clamp(int val,int minVal,int maxVal)1532 int Platform::Clamp(int val, int minVal, int maxVal) {
1533 if (val > maxVal)
1534 val = maxVal;
1535 if (val < minVal)
1536 val = minVal;
1537 return val;
1538 }
1539