1 // Scintilla source code edit control
2 /** @file Platform.h
3  ** Interface to platform facilities. Also includes some basic utilities.
4  ** Implemented in PlatGTK.cxx for GTK+/Linux, PlatWin.cxx for Windows, and PlatWX.cxx for wxWindows.
5  **/
6 // Copyright 1998-2009 by Neil Hodgson <neilh@scintilla.org>
7 // The License.txt file describes the conditions under which this software may be distributed.
8 
9 #ifndef PLATFORM_H
10 #define PLATFORM_H
11 
12 // PLAT_GTK = GTK+ on Linux or Win32
13 // PLAT_GTK_WIN32 is defined additionally when running PLAT_GTK under Win32
14 // PLAT_WIN = Win32 API on Win32 OS
15 // PLAT_WX is wxWindows on any supported platform
16 
17 #define PLAT_GTK 0
18 #define PLAT_GTK_WIN32 0
19 #define PLAT_GTK_MACOSX 0
20 #define PLAT_MACOSX 0
21 #define PLAT_WIN 0
22 #define PLAT_WX  0
23 #define PLAT_FOX 0
24 
25 #if defined(FOX)
26 #undef PLAT_FOX
27 #define PLAT_FOX 1
28 
29 #elif defined(__WX__)
30 #undef PLAT_WX
31 #define PLAT_WX  1
32 
33 #elif defined(GTK)
34 #undef PLAT_GTK
35 #define PLAT_GTK 1
36 
37 #if defined(__WIN32__) || defined(_MSC_VER)
38 #undef PLAT_GTK_WIN32
39 #define PLAT_GTK_WIN32 1
40 #endif
41 
42 #if defined(__APPLE__)
43 #undef PLAT_GTK_MACOSX
44 #define PLAT_GTK_MACOSX 1
45 #endif
46 
47 #elif defined(__APPLE__)
48 
49 #undef PLAT_MACOSX
50 #define PLAT_MACOSX 1
51 
52 #else
53 #undef PLAT_WIN
54 #define PLAT_WIN 1
55 
56 #endif
57 
58 #ifdef SCI_NAMESPACE
59 namespace Scintilla {
60 #endif
61 
62 // Underlying the implementation of the platform classes are platform specific types.
63 // Sometimes these need to be passed around by client code so they are defined here
64 
65 #if PLAT_FOX
66 
67 namespace FX {
68 
69 class FXFont;
70 class FXDrawable;
71 class FXWindow;
72 class FXMenuPane;
73 class FXList;
74 class FXChore;
75 # ifndef WIN32
76 class FXTimer;
77 # else
78 struct FXTimer;
79 # endif	// WIN32
80 
81 };
82 using namespace FX;
83 
84 typedef FXFont * FontID;
85 typedef void * SurfaceID;
86 typedef FXWindow * WindowID;
87 typedef FXMenuPane * MenuID;
88 typedef FXTimer * TickerID;
89 typedef FXChore * IdlerID;
90 #else
91 typedef void *FontID;
92 typedef void *SurfaceID;
93 typedef void *WindowID;
94 typedef void *MenuID;
95 typedef void *TickerID;
96 typedef void *IdlerID;
97 #endif
98 typedef void *Function;
99 
100 /**
101  * A geometric point class.
102  * Point is exactly the same as the Win32 POINT and GTK+ GdkPoint so can be used interchangeably.
103  */
104 class Point {
105 public:
106 	int x;
107 	int y;
108 
x(x_)109 	explicit Point(int x_=0, int y_=0) : x(x_), y(y_) {
110 	}
111 
112 	// Other automatically defined methods (assignment, copy constructor, destructor) are fine
113 
114 	static Point FromLong(long lpoint);
115 };
116 
117 /**
118  * A geometric rectangle class.
119  * PRectangle is exactly the same as the Win32 RECT so can be used interchangeably.
120  * PRectangles contain their top and left sides, but not their right and bottom sides.
121  */
122 class PRectangle {
123 public:
124 	int left;
125 	int top;
126 	int right;
127 	int bottom;
128 
129 	PRectangle(int left_=0, int top_=0, int right_=0, int bottom_ = 0) :
left(left_)130 		left(left_), top(top_), right(right_), bottom(bottom_) {
131 	}
132 
133 	// Other automatically defined methods (assignment, copy constructor, destructor) are fine
134 
135 	bool operator==(PRectangle &rc) {
136 		return (rc.left == left) && (rc.right == right) &&
137 			(rc.top == top) && (rc.bottom == bottom);
138 	}
Contains(Point pt)139 	bool Contains(Point pt) {
140 		return (pt.x >= left) && (pt.x <= right) &&
141 			(pt.y >= top) && (pt.y <= bottom);
142 	}
Contains(PRectangle rc)143 	bool Contains(PRectangle rc) {
144 		return (rc.left >= left) && (rc.right <= right) &&
145 			(rc.top >= top) && (rc.bottom <= bottom);
146 	}
Intersects(PRectangle other)147 	bool Intersects(PRectangle other) {
148 		return (right > other.left) && (left < other.right) &&
149 			(bottom > other.top) && (top < other.bottom);
150 	}
Move(int xDelta,int yDelta)151 	void Move(int xDelta, int yDelta) {
152 		left += xDelta;
153 		top += yDelta;
154 		right += xDelta;
155 		bottom += yDelta;
156 	}
Width()157 	int Width() { return right - left; }
Height()158 	int Height() { return bottom - top; }
Empty()159 	bool Empty() {
160 		return (Height() <= 0) || (Width() <= 0);
161 	}
162 };
163 
164 /**
165  * In some circumstances, including Win32 in paletted mode and GTK+, each colour
166  * must be allocated before use. The desired colours are held in the ColourDesired class,
167  * and after allocation the allocation entry is stored in the ColourAllocated class. In other
168  * circumstances, such as Win32 in true colour mode, the allocation process just copies
169  * the RGB values from the desired to the allocated class.
170  * As each desired colour requires allocation before it can be used, the ColourPair class
171  * holds both a ColourDesired and a ColourAllocated
172  * The Palette class is responsible for managing the palette of colours which contains a
173  * list of ColourPair objects and performs the allocation.
174  */
175 
176 /**
177  * Holds a desired RGB colour.
178  */
179 class ColourDesired {
180 	long co;
181 public:
182 	ColourDesired(long lcol=0) {
183 		co = lcol;
184 	}
185 
ColourDesired(unsigned int red,unsigned int green,unsigned int blue)186 	ColourDesired(unsigned int red, unsigned int green, unsigned int blue) {
187 		Set(red, green, blue);
188 	}
189 
190 	bool operator==(const ColourDesired &other) const {
191 		return co == other.co;
192 	}
193 
Set(long lcol)194 	void Set(long lcol) {
195 		co = lcol;
196 	}
197 
Set(unsigned int red,unsigned int green,unsigned int blue)198 	void Set(unsigned int red, unsigned int green, unsigned int blue) {
199 		co = red | (green << 8) | (blue << 16);
200 	}
201 
ValueOfHex(const char ch)202 	static inline unsigned int ValueOfHex(const char ch) {
203 		if (ch >= '0' && ch <= '9')
204 			return ch - '0';
205 		else if (ch >= 'A' && ch <= 'F')
206 			return ch - 'A' + 10;
207 		else if (ch >= 'a' && ch <= 'f')
208 			return ch - 'a' + 10;
209 		else
210 			return 0;
211 	}
212 
Set(const char * val)213 	void Set(const char *val) {
214 		if (*val == '#') {
215 			val++;
216 		}
217 		unsigned int r = ValueOfHex(val[0]) * 16 + ValueOfHex(val[1]);
218 		unsigned int g = ValueOfHex(val[2]) * 16 + ValueOfHex(val[3]);
219 		unsigned int b = ValueOfHex(val[4]) * 16 + ValueOfHex(val[5]);
220 		Set(r, g, b);
221 	}
222 
AsLong()223 	long AsLong() const {
224 		return co;
225 	}
226 
GetRed()227 	unsigned int GetRed() {
228 		return co & 0xff;
229 	}
230 
GetGreen()231 	unsigned int GetGreen() {
232 		return (co >> 8) & 0xff;
233 	}
234 
GetBlue()235 	unsigned int GetBlue() {
236 		return (co >> 16) & 0xff;
237 	}
238 };
239 
240 /**
241  * Holds an allocated RGB colour which may be an approximation to the desired colour.
242  */
243 class ColourAllocated {
244 	long coAllocated;
245 
246 public:
247 
248 	ColourAllocated(long lcol=0) {
249 		coAllocated = lcol;
250 	}
251 
Set(long lcol)252 	void Set(long lcol) {
253 		coAllocated = lcol;
254 	}
255 
AsLong()256 	long AsLong() const {
257 		return coAllocated;
258 	}
259 };
260 
261 /**
262  * Colour pairs hold a desired colour and an allocated colour.
263  */
264 struct ColourPair {
265 	ColourDesired desired;
266 	ColourAllocated allocated;
267 
268 	ColourPair(ColourDesired desired_=ColourDesired(0,0,0)) {
269 		desired = desired_;
270 		allocated.Set(desired.AsLong());
271 	}
CopyColourPair272 	void Copy() {
273 		allocated.Set(desired.AsLong());
274 	}
275 };
276 
277 class Window;	// Forward declaration for Palette
278 
279 /**
280  * Colour palette management.
281  */
282 class Palette {
283 	int used;
284 	int size;
285 	ColourPair *entries;
286 #if PLAT_GTK
287 	void *allocatedPalette; // GdkColor *
288 	int allocatedLen;
289 #elif PLAT_FOX
290 	void * visual;
291 #endif
292 	// Private so Palette objects can not be copied
293 	Palette(const Palette &);
294 	Palette &operator=(const Palette &);
295 public:
296 #if PLAT_WIN
297 	void *hpal;
298 #endif
299 	bool allowRealization;
300 
301 	Palette();
302 	~Palette();
303 
304 	void Release();
305 
306 	/**
307 	 * This method either adds a colour to the list of wanted colours (want==true)
308 	 * or retrieves the allocated colour back to the ColourPair.
309 	 * This is one method to make it easier to keep the code for wanting and retrieving in sync.
310 	 */
311 	void WantFind(ColourPair &cp, bool want);
312 
313 	void Allocate(Window &w);
314 };
315 
316 /**
317  * Font management.
318  */
319 class Font {
320 protected:
321 	FontID fid;
322 #if PLAT_WX
323 	int ascent;
324 #endif
325 	// Private so Font objects can not be copied
326 	Font(const Font &);
327 	Font &operator=(const Font &);
328 public:
329 	Font();
330 	virtual ~Font();
331 
332 	virtual void Create(const char *faceName, int characterSet, int size,
333 		bool bold, bool italic, int extraFontFlag=0);
334 	virtual void Release();
335 
GetID()336 	FontID GetID() { return fid; }
337 	// Alias another font - caller guarantees not to Release
SetID(FontID fid_)338 	void SetID(FontID fid_) { fid = fid_; }
339 #if PLAT_WX
SetAscent(int ascent_)340 	void SetAscent(int ascent_) { ascent = ascent_; }
341 #endif
342 	friend class Surface;
343 	friend class SurfaceImpl;
344 };
345 
346 /**
347  * A surface abstracts a place to draw.
348  */
349 class Surface {
350 private:
351 	// Private so Surface objects can not be copied
Surface(const Surface &)352 	Surface(const Surface &) {}
353 	Surface &operator=(const Surface &) { return *this; }
354 public:
Surface()355 	Surface() {}
~Surface()356 	virtual ~Surface() {}
357 	static Surface *Allocate();
358 
359 	virtual void Init(WindowID wid)=0;
360 	virtual void Init(SurfaceID sid, WindowID wid)=0;
361 	virtual void InitPixMap(int width, int height, Surface *surface_, WindowID wid)=0;
362 
363 	virtual void Release()=0;
364 	virtual bool Initialised()=0;
365 	virtual void PenColour(ColourAllocated fore)=0;
366 	virtual int LogPixelsY()=0;
367 	virtual int DeviceHeightFont(int points)=0;
368 	virtual void MoveTo(int x_, int y_)=0;
369 	virtual void LineTo(int x_, int y_)=0;
370 	virtual void Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back)=0;
371 	virtual void RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back)=0;
372 	virtual void FillRectangle(PRectangle rc, ColourAllocated back)=0;
373 	virtual void FillRectangle(PRectangle rc, Surface &surfacePattern)=0;
374 	virtual void RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back)=0;
375 	virtual void AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill,
376 		ColourAllocated outline, int alphaOutline, int flags)=0;
377 	virtual void DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage) = 0;
378 	virtual void Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back)=0;
379 	virtual void Copy(PRectangle rc, Point from, Surface &surfaceSource)=0;
380 
381 	virtual void DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back)=0;
382 	virtual void DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back)=0;
383 	virtual void DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore)=0;
384 	virtual void MeasureWidths(Font &font_, const char *s, int len, int *positions)=0;
385 	virtual int WidthText(Font &font_, const char *s, int len)=0;
386 	virtual int WidthChar(Font &font_, char ch)=0;
387 	virtual int Ascent(Font &font_)=0;
388 	virtual int Descent(Font &font_)=0;
389 	virtual int InternalLeading(Font &font_)=0;
390 	virtual int ExternalLeading(Font &font_)=0;
391 	virtual int Height(Font &font_)=0;
392 	virtual int AverageCharWidth(Font &font_)=0;
393 
394 	virtual int SetPalette(Palette *pal, bool inBackGround)=0;
395 	virtual void SetClip(PRectangle rc)=0;
396 	virtual void FlushCachedState()=0;
397 
398 	virtual void SetUnicodeMode(bool unicodeMode_)=0;
399 	virtual void SetDBCSMode(int codePage)=0;
400 };
401 
402 /**
403  * A simple callback action passing one piece of untyped user data.
404  */
405 typedef void (*CallBackAction)(void*);
406 
407 /**
408  * Class to hide the details of window manipulation.
409  * Does not own the window which will normally have a longer life than this object.
410  */
411 class Window {
412 protected:
413 	WindowID wid;
414 #if PLAT_MACOSX
415 	void *windowRef;
416 	void *control;
417 #endif
418 public:
Window()419 	Window() : wid(0), cursorLast(cursorInvalid) {
420 #if PLAT_MACOSX
421 	  windowRef = 0;
422 	  control = 0;
423 #endif
424 	}
Window(const Window & source)425 	Window(const Window &source) : wid(source.wid), cursorLast(cursorInvalid) {
426 #if PLAT_MACOSX
427 	  windowRef = 0;
428 	  control = 0;
429 #endif
430 	}
431 	virtual ~Window();
432 	Window &operator=(WindowID wid_) {
433 		wid = wid_;
434 		return *this;
435 	}
GetID()436 	WindowID GetID() const { return wid; }
Created()437 	bool Created() const { return wid != 0; }
438 	void Destroy();
439 	bool HasFocus();
440 	PRectangle GetPosition();
441 	void SetPosition(PRectangle rc);
442 	void SetPositionRelative(PRectangle rc, Window relativeTo);
443 	PRectangle GetClientPosition();
444 #if PLAT_FOX
445 	virtual
446 #endif
447 	void Show(bool show=true);
448 	void InvalidateAll();
449 	void InvalidateRectangle(PRectangle rc);
450 	virtual void SetFont(Font &font);
451 	enum Cursor { cursorInvalid, cursorText, cursorArrow, cursorUp, cursorWait, cursorHoriz, cursorVert, cursorReverseArrow, cursorHand };
452 	void SetCursor(Cursor curs);
453 	void SetTitle(const char *s);
454 	PRectangle GetMonitorRect(Point pt);
455 #if PLAT_MACOSX
SetWindow(void * ref)456 	void SetWindow(void *ref) { windowRef = ref; }
SetControl(void * _control)457 	void SetControl(void *_control) { control = _control; }
458 #endif
459 private:
460 	Cursor cursorLast;
461 };
462 
463 /**
464  * Listbox management.
465  */
466 class ListBox : public Window {
467 public:
468 	ListBox();
469 	virtual ~ListBox();
470 	static ListBox *Allocate();
471 
472 	virtual void SetFont(Font &font)=0;
473 	virtual void Create(Window &parent, int ctrlID, Point location, int lineHeight_, bool unicodeMode_)=0;
474 	virtual void SetAverageCharWidth(int width)=0;
475 	virtual void SetVisibleRows(int rows)=0;
476 	virtual int GetVisibleRows() const=0;
477 	virtual PRectangle GetDesiredRect()=0;
478 	virtual int CaretFromEdge()=0;
479 	virtual void Clear()=0;
480 	virtual void Append(char *s, int type = -1)=0;
481 	virtual int Length()=0;
482 	virtual void Select(int n)=0;
483 	virtual int GetSelection()=0;
484 	virtual int Find(const char *prefix)=0;
485 	virtual void GetValue(int n, char *value, int len)=0;
486 	virtual void RegisterImage(int type, const char *xpm_data)=0;
487 	virtual void RegisterRGBAImage(int type, int width, int height, const unsigned char *pixelsImage) = 0;
488 	virtual void ClearRegisteredImages()=0;
489 	virtual void SetDoubleClickAction(CallBackAction, void *)=0;
490 	virtual void SetList(const char* list, char separator, char typesep)=0;
491 };
492 
493 /**
494  * Menu management.
495  */
496 class Menu {
497 	MenuID mid;
498 public:
499 	Menu();
GetID()500 	MenuID GetID() { return mid; }
501 	void CreatePopUp();
502 	void Destroy();
503 	void Show(Point pt, Window &w);
504 };
505 
506 class ElapsedTime {
507 	long bigBit;
508 	long littleBit;
509 public:
510 	ElapsedTime();
511 	double Duration(bool reset=false);
512 };
513 
514 /**
515  * Dynamic Library (DLL/SO/...) loading
516  */
517 class DynamicLibrary {
518 public:
~DynamicLibrary()519 	virtual ~DynamicLibrary() {}
520 
521 	/// @return Pointer to function "name", or NULL on failure.
522 	virtual Function FindFunction(const char *name) = 0;
523 
524 	/// @return true if the library was loaded successfully.
525 	virtual bool IsValid() = 0;
526 
527 	/// @return An instance of a DynamicLibrary subclass with "modulePath" loaded.
528 	static DynamicLibrary *Load(const char *modulePath);
529 };
530 
531 /**
532  * Platform class used to retrieve system wide parameters such as double click speed
533  * and chrome colour. Not a creatable object, more of a module with several functions.
534  */
535 class Platform {
536 	// Private so Platform objects can not be copied
Platform(const Platform &)537 	Platform(const Platform &) {}
538 	Platform &operator=(const Platform &) { return *this; }
539 public:
540 	// Should be private because no new Platforms are ever created
541 	// but gcc warns about this
Platform()542 	Platform() {}
~Platform()543 	~Platform() {}
544 	static ColourDesired Chrome();
545 	static ColourDesired ChromeHighlight();
546 	static const char *DefaultFont();
547 	static int DefaultFontSize();
548 	static unsigned int DoubleClickTime();
549 	static bool MouseButtonBounce();
550 	static void DebugDisplay(const char *s);
551 	static bool IsKeyDown(int key);
552 	static long SendScintilla(
553 		WindowID w, unsigned int msg, unsigned long wParam=0, long lParam=0);
554 	static long SendScintillaPointer(
555 		WindowID w, unsigned int msg, unsigned long wParam=0, void *lParam=0);
556 	static bool IsDBCSLeadByte(int codePage, char ch);
557 	static int DBCSCharLength(int codePage, const char *s);
558 	static int DBCSCharMaxLength();
559 
560 	// These are utility functions not really tied to a platform
561 	static int Minimum(int a, int b);
562 	static int Maximum(int a, int b);
563 	// Next three assume 16 bit shorts and 32 bit longs
LongFromTwoShorts(short a,short b)564 	static long LongFromTwoShorts(short a,short b) {
565 		return (a) | ((b) << 16);
566 	}
HighShortFromLong(long x)567 	static short HighShortFromLong(long x) {
568 		return static_cast<short>(x >> 16);
569 	}
LowShortFromLong(long x)570 	static short LowShortFromLong(long x) {
571 		return static_cast<short>(x & 0xffff);
572 	}
573 	static void DebugPrintf(const char *format, ...);
574 	static bool ShowAssertionPopUps(bool assertionPopUps_);
575 	static void Assert(const char *c, const char *file, int line);
576 	static int Clamp(int val, int minVal, int maxVal);
577 };
578 
579 #ifdef  NDEBUG
580 #define PLATFORM_ASSERT(c) ((void)0)
581 #else
582 #ifdef SCI_NAMESPACE
583 #define PLATFORM_ASSERT(c) ((c) ? (void)(0) : Scintilla::Platform::Assert(#c, __FILE__, __LINE__))
584 #else
585 #define PLATFORM_ASSERT(c) ((c) ? (void)(0) : Platform::Assert(#c, __FILE__, __LINE__))
586 #endif
587 #endif
588 
589 #ifdef SCI_NAMESPACE
590 }
591 #endif
592 
593 // Shut up annoying Visual C++ warnings:
594 #ifdef _MSC_VER
595 #pragma warning(disable: 4244 4309 4514 4710)
596 #endif
597 
598 #endif
599