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 <[email protected]> 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 // PLAT_TK = Tcl/TK on Linux or Win32 17 18 #define PLAT_GTK 0 19 #define PLAT_GTK_WIN32 0 20 #define PLAT_GTK_MACOSX 0 21 #define PLAT_MACOSX 0 22 #define PLAT_WIN 0 23 #define PLAT_WX 0 24 #define PLAT_QT 0 25 #define PLAT_FOX 0 26 #define PLAT_CURSES 0 27 #define PLAT_TK 0 28 #define PLAT_HAIKU 0 29 30 #if defined(FOX) 31 #undef PLAT_FOX 32 #define PLAT_FOX 1 33 34 #elif defined(__WX__) 35 #undef PLAT_WX 36 #define PLAT_WX 1 37 38 #elif defined(CURSES) 39 #undef PLAT_CURSES 40 #define PLAT_CURSES 1 41 42 #elif defined(__HAIKU__) 43 #undef PLAT_HAIKU 44 #define PLAT_HAIKU 1 45 46 #elif defined(SCINTILLA_QT) 47 #undef PLAT_QT 48 #define PLAT_QT 1 49 50 #elif defined(TK) 51 #undef PLAT_TK 52 #define PLAT_TK 1 53 54 #elif defined(GTK) 55 #undef PLAT_GTK 56 #define PLAT_GTK 1 57 58 #if defined(__WIN32__) || defined(_MSC_VER) 59 #undef PLAT_GTK_WIN32 60 #define PLAT_GTK_WIN32 1 61 #endif 62 63 #if defined(__APPLE__) 64 #undef PLAT_GTK_MACOSX 65 #define PLAT_GTK_MACOSX 1 66 #endif 67 68 #elif defined(__APPLE__) 69 70 #undef PLAT_MACOSX 71 #define PLAT_MACOSX 1 72 73 #else 74 #undef PLAT_WIN 75 #define PLAT_WIN 1 76 77 #endif 78 79 namespace Scintilla { 80 81 typedef float XYPOSITION; 82 typedef double XYACCUMULATOR; 83 84 // Underlying the implementation of the platform classes are platform specific types. 85 // Sometimes these need to be passed around by client code so they are defined here 86 87 typedef void *FontID; 88 typedef void *SurfaceID; 89 typedef void *WindowID; 90 typedef void *MenuID; 91 typedef void *TickerID; 92 typedef void *Function; 93 typedef void *IdlerID; 94 95 /** 96 * A geometric point class. 97 * Point is similar to the Win32 POINT and GTK+ GdkPoint types. 98 */ 99 class Point { 100 public: 101 XYPOSITION x; 102 XYPOSITION y; 103 x(x_)104 constexpr explicit Point(XYPOSITION x_=0, XYPOSITION y_=0) noexcept : x(x_), y(y_) { 105 } 106 FromInts(int x_,int y_)107 static constexpr Point FromInts(int x_, int y_) noexcept { 108 return Point(static_cast<XYPOSITION>(x_), static_cast<XYPOSITION>(y_)); 109 } 110 111 constexpr bool operator!=(Point other) const noexcept { 112 return (x != other.x) || (y != other.y); 113 } 114 115 constexpr Point operator+(Point other) const noexcept { 116 return Point(x + other.x, y + other.y); 117 } 118 119 constexpr Point operator-(Point other) const noexcept { 120 return Point(x - other.x, y - other.y); 121 } 122 123 // Other automatically defined methods (assignment, copy constructor, destructor) are fine 124 }; 125 126 /** 127 * A geometric rectangle class. 128 * PRectangle is similar to Win32 RECT. 129 * PRectangles contain their top and left sides, but not their right and bottom sides. 130 */ 131 class PRectangle { 132 public: 133 XYPOSITION left; 134 XYPOSITION top; 135 XYPOSITION right; 136 XYPOSITION bottom; 137 138 constexpr explicit PRectangle(XYPOSITION left_=0, XYPOSITION top_=0, XYPOSITION right_=0, XYPOSITION bottom_ = 0) noexcept : left(left_)139 left(left_), top(top_), right(right_), bottom(bottom_) { 140 } 141 FromInts(int left_,int top_,int right_,int bottom_)142 static constexpr PRectangle FromInts(int left_, int top_, int right_, int bottom_) noexcept { 143 return PRectangle(static_cast<XYPOSITION>(left_), static_cast<XYPOSITION>(top_), 144 static_cast<XYPOSITION>(right_), static_cast<XYPOSITION>(bottom_)); 145 } 146 147 // Other automatically defined methods (assignment, copy constructor, destructor) are fine 148 149 constexpr bool operator==(const PRectangle &rc) const noexcept { 150 return (rc.left == left) && (rc.right == right) && 151 (rc.top == top) && (rc.bottom == bottom); 152 } Contains(Point pt)153 constexpr bool Contains(Point pt) const noexcept { 154 return (pt.x >= left) && (pt.x <= right) && 155 (pt.y >= top) && (pt.y <= bottom); 156 } ContainsWholePixel(Point pt)157 constexpr bool ContainsWholePixel(Point pt) const noexcept { 158 // Does the rectangle contain all of the pixel to left/below the point 159 return (pt.x >= left) && ((pt.x+1) <= right) && 160 (pt.y >= top) && ((pt.y+1) <= bottom); 161 } Contains(PRectangle rc)162 constexpr bool Contains(PRectangle rc) const noexcept { 163 return (rc.left >= left) && (rc.right <= right) && 164 (rc.top >= top) && (rc.bottom <= bottom); 165 } Intersects(PRectangle other)166 constexpr bool Intersects(PRectangle other) const noexcept { 167 return (right > other.left) && (left < other.right) && 168 (bottom > other.top) && (top < other.bottom); 169 } Move(XYPOSITION xDelta,XYPOSITION yDelta)170 void Move(XYPOSITION xDelta, XYPOSITION yDelta) noexcept { 171 left += xDelta; 172 top += yDelta; 173 right += xDelta; 174 bottom += yDelta; 175 } Width()176 constexpr XYPOSITION Width() const noexcept { return right - left; } Height()177 constexpr XYPOSITION Height() const noexcept { return bottom - top; } Empty()178 constexpr bool Empty() const noexcept { 179 return (Height() <= 0) || (Width() <= 0); 180 } 181 }; 182 183 /** 184 * Holds an RGB colour with 8 bits for each component. 185 */ 186 constexpr const float componentMaximum = 255.0f; 187 class ColourDesired { 188 int co; 189 public: co(co_)190 constexpr explicit ColourDesired(int co_=0) noexcept : co(co_) { 191 } 192 ColourDesired(unsigned int red,unsigned int green,unsigned int blue)193 constexpr ColourDesired(unsigned int red, unsigned int green, unsigned int blue) noexcept : 194 co(red | (green << 8) | (blue << 16)) { 195 } 196 197 constexpr bool operator==(const ColourDesired &other) const noexcept { 198 return co == other.co; 199 } 200 AsInteger()201 constexpr int AsInteger() const noexcept { 202 return co; 203 } 204 205 // Red, green and blue values as bytes 0..255 GetRed()206 constexpr unsigned char GetRed() const noexcept { 207 return co & 0xff; 208 } GetGreen()209 constexpr unsigned char GetGreen() const noexcept { 210 return (co >> 8) & 0xff; 211 } GetBlue()212 constexpr unsigned char GetBlue() const noexcept { 213 return (co >> 16) & 0xff; 214 } 215 216 // Red, green and blue values as float 0..1.0 GetRedComponent()217 constexpr float GetRedComponent() const noexcept { 218 return GetRed() / componentMaximum; 219 } GetGreenComponent()220 constexpr float GetGreenComponent() const noexcept { 221 return GetGreen() / componentMaximum; 222 } GetBlueComponent()223 constexpr float GetBlueComponent() const noexcept { 224 return GetBlue() / componentMaximum; 225 } 226 }; 227 228 /** 229 * Holds an RGBA colour. 230 */ 231 class ColourAlpha : public ColourDesired { 232 public: ColourDesired(co_)233 constexpr explicit ColourAlpha(int co_ = 0) noexcept : ColourDesired(co_) { 234 } 235 ColourAlpha(unsigned int red,unsigned int green,unsigned int blue)236 constexpr ColourAlpha(unsigned int red, unsigned int green, unsigned int blue) noexcept : 237 ColourDesired(red | (green << 8) | (blue << 16)) { 238 } 239 ColourAlpha(unsigned int red,unsigned int green,unsigned int blue,unsigned int alpha)240 constexpr ColourAlpha(unsigned int red, unsigned int green, unsigned int blue, unsigned int alpha) noexcept : 241 ColourDesired(red | (green << 8) | (blue << 16) | (alpha << 24)) { 242 } 243 ColourAlpha(ColourDesired cd,unsigned int alpha)244 constexpr ColourAlpha(ColourDesired cd, unsigned int alpha) noexcept : 245 ColourDesired(cd.AsInteger() | (alpha << 24)) { 246 } 247 GetColour()248 constexpr ColourDesired GetColour() const noexcept { 249 return ColourDesired(AsInteger() & 0xffffff); 250 } 251 GetAlpha()252 constexpr unsigned char GetAlpha() const noexcept { 253 return (AsInteger() >> 24) & 0xff; 254 } 255 GetAlphaComponent()256 constexpr float GetAlphaComponent() const noexcept { 257 return GetAlpha() / componentMaximum; 258 } 259 MixedWith(ColourAlpha other)260 constexpr ColourAlpha MixedWith(ColourAlpha other) const noexcept { 261 const unsigned int red = (GetRed() + other.GetRed()) / 2; 262 const unsigned int green = (GetGreen() + other.GetGreen()) / 2; 263 const unsigned int blue = (GetBlue() + other.GetBlue()) / 2; 264 const unsigned int alpha = (GetAlpha() + other.GetAlpha()) / 2; 265 return ColourAlpha(red, green, blue, alpha); 266 } 267 }; 268 269 /** 270 * Holds an element of a gradient with an RGBA colour and a relative position. 271 */ 272 class ColourStop { 273 public: 274 float position; 275 ColourAlpha colour; ColourStop(float position_,ColourAlpha colour_)276 ColourStop(float position_, ColourAlpha colour_) noexcept : 277 position(position_), colour(colour_) { 278 } 279 }; 280 281 /** 282 * Font management. 283 */ 284 285 struct FontParameters { 286 const char *faceName; 287 float size; 288 int weight; 289 bool italic; 290 int extraFontFlag; 291 int technology; 292 int characterSet; 293 294 FontParameters( 295 const char *faceName_, 296 float size_=10, 297 int weight_=400, 298 bool italic_=false, 299 int extraFontFlag_=0, 300 int technology_=0, 301 int characterSet_=0) noexcept : 302 faceNameFontParameters303 faceName(faceName_), 304 size(size_), 305 weight(weight_), 306 italic(italic_), 307 extraFontFlag(extraFontFlag_), 308 technology(technology_), 309 characterSet(characterSet_) 310 { 311 } 312 313 }; 314 315 class Font { 316 protected: 317 FontID fid; 318 public: 319 Font() noexcept; 320 // Deleted so Font objects can not be copied 321 Font(const Font &) = delete; 322 Font(Font &&) = delete; 323 Font &operator=(const Font &) = delete; 324 Font &operator=(Font &&) = delete; 325 virtual ~Font(); 326 327 virtual void Create(const FontParameters &fp); 328 virtual void Release(); 329 GetID()330 FontID GetID() const noexcept { return fid; } 331 // Alias another font - caller guarantees not to Release SetID(FontID fid_)332 void SetID(FontID fid_) noexcept { fid = fid_; } 333 friend class Surface; 334 friend class SurfaceImpl; 335 }; 336 337 class IScreenLine { 338 public: 339 virtual std::string_view Text() const = 0; 340 virtual size_t Length() const = 0; 341 virtual size_t RepresentationCount() const = 0; 342 virtual XYPOSITION Width() const = 0; 343 virtual XYPOSITION Height() const = 0; 344 virtual XYPOSITION TabWidth() const = 0; 345 virtual XYPOSITION TabWidthMinimumPixels() const = 0; 346 virtual const Font *FontOfPosition(size_t position) const = 0; 347 virtual XYPOSITION RepresentationWidth(size_t position) const = 0; 348 virtual XYPOSITION TabPositionAfter(XYPOSITION xPosition) const = 0; 349 }; 350 351 struct Interval { 352 XYPOSITION left; 353 XYPOSITION right; 354 }; 355 356 class IScreenLineLayout { 357 public: 358 virtual ~IScreenLineLayout() = default; 359 virtual size_t PositionFromX(XYPOSITION xDistance, bool charPosition) = 0; 360 virtual XYPOSITION XFromPosition(size_t caretPosition) = 0; 361 virtual std::vector<Interval> FindRangeIntervals(size_t start, size_t end) = 0; 362 }; 363 364 /** 365 * A surface abstracts a place to draw. 366 */ 367 class Surface { 368 public: 369 Surface() noexcept = default; 370 Surface(const Surface &) = delete; 371 Surface(Surface &&) = delete; 372 Surface &operator=(const Surface &) = delete; 373 Surface &operator=(Surface &&) = delete; ~Surface()374 virtual ~Surface() {} 375 static Surface *Allocate(int technology); 376 377 virtual void Init(WindowID wid)=0; 378 virtual void Init(SurfaceID sid, WindowID wid)=0; 379 virtual void InitPixMap(int width, int height, Surface *surface_, WindowID wid)=0; 380 381 virtual void Release()=0; 382 virtual bool Initialised()=0; 383 virtual void PenColour(ColourDesired fore)=0; 384 virtual int LogPixelsY()=0; 385 virtual int DeviceHeightFont(int points)=0; 386 virtual void MoveTo(int x_, int y_)=0; 387 virtual void LineTo(int x_, int y_)=0; 388 virtual void Polygon(Point *pts, size_t npts, ColourDesired fore, ColourDesired back)=0; 389 virtual void RectangleDraw(PRectangle rc, ColourDesired fore, ColourDesired back)=0; 390 virtual void FillRectangle(PRectangle rc, ColourDesired back)=0; 391 virtual void FillRectangle(PRectangle rc, Surface &surfacePattern)=0; 392 virtual void RoundedRectangle(PRectangle rc, ColourDesired fore, ColourDesired back)=0; 393 virtual void AlphaRectangle(PRectangle rc, int cornerSize, ColourDesired fill, int alphaFill, 394 ColourDesired outline, int alphaOutline, int flags)=0; 395 enum class GradientOptions { leftToRight, topToBottom }; 396 virtual void GradientRectangle(PRectangle rc, const std::vector<ColourStop> &stops, GradientOptions options)=0; 397 virtual void DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage) = 0; 398 virtual void Ellipse(PRectangle rc, ColourDesired fore, ColourDesired back)=0; 399 virtual void Copy(PRectangle rc, Point from, Surface &surfaceSource)=0; 400 401 virtual std::unique_ptr<IScreenLineLayout> Layout(const IScreenLine *screenLine) = 0; 402 403 virtual void DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, std::string_view text, ColourDesired fore, ColourDesired back) = 0; 404 virtual void DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, std::string_view text, ColourDesired fore, ColourDesired back) = 0; 405 virtual void DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, std::string_view text, ColourDesired fore) = 0; 406 virtual void MeasureWidths(Font &font_, std::string_view text, XYPOSITION *positions) = 0; 407 virtual XYPOSITION WidthText(Font &font_, std::string_view text) = 0; 408 virtual XYPOSITION Ascent(Font &font_)=0; 409 virtual XYPOSITION Descent(Font &font_)=0; 410 virtual XYPOSITION InternalLeading(Font &font_)=0; 411 virtual XYPOSITION Height(Font &font_)=0; 412 virtual XYPOSITION AverageCharWidth(Font &font_)=0; 413 414 virtual void SetClip(PRectangle rc)=0; 415 virtual void FlushCachedState()=0; 416 417 virtual void SetUnicodeMode(bool unicodeMode_)=0; 418 virtual void SetDBCSMode(int codePage)=0; 419 virtual void SetBidiR2L(bool bidiR2L_)=0; 420 }; 421 422 /** 423 * Class to hide the details of window manipulation. 424 * Does not own the window which will normally have a longer life than this object. 425 */ 426 class Window { 427 protected: 428 WindowID wid; 429 public: Window()430 Window() noexcept : wid(nullptr), cursorLast(cursorInvalid) { 431 } 432 Window(const Window &source) = delete; 433 Window(Window &&) = delete; 434 Window &operator=(WindowID wid_) noexcept { 435 wid = wid_; 436 cursorLast = cursorInvalid; 437 return *this; 438 } 439 Window &operator=(const Window &) = delete; 440 Window &operator=(Window &&) = delete; 441 virtual ~Window(); GetID()442 WindowID GetID() const noexcept { return wid; } Created()443 bool Created() const noexcept { return wid != nullptr; } 444 void Destroy(); 445 PRectangle GetPosition() const; 446 void SetPosition(PRectangle rc); 447 void SetPositionRelative(PRectangle rc, const Window *relativeTo); 448 PRectangle GetClientPosition() const; 449 void Show(bool show=true); 450 void InvalidateAll(); 451 void InvalidateRectangle(PRectangle rc); 452 virtual void SetFont(Font &font); 453 enum Cursor { cursorInvalid, cursorText, cursorArrow, cursorUp, cursorWait, cursorHoriz, cursorVert, cursorReverseArrow, cursorHand }; 454 void SetCursor(Cursor curs); 455 PRectangle GetMonitorRect(Point pt); 456 private: 457 Cursor cursorLast; 458 }; 459 460 /** 461 * Listbox management. 462 */ 463 464 // ScintillaBase implements IListBoxDelegate to receive ListBoxEvents from a ListBox 465 466 struct ListBoxEvent { 467 enum class EventType { selectionChange, doubleClick } event; ListBoxEventListBoxEvent468 ListBoxEvent(EventType event_) noexcept : event(event_) { 469 } 470 }; 471 472 class IListBoxDelegate { 473 public: 474 virtual void ListNotify(ListBoxEvent *plbe)=0; 475 }; 476 477 class ListBox : public Window { 478 public: 479 ListBox() noexcept; 480 ~ListBox() override; 481 static ListBox *Allocate(); 482 483 void SetFont(Font &font) override =0; 484 virtual void Create(Window &parent, int ctrlID, Point location, int lineHeight_, bool unicodeMode_, int technology_)=0; 485 virtual void SetAverageCharWidth(int width)=0; 486 virtual void SetVisibleRows(int rows)=0; 487 virtual int GetVisibleRows() const=0; 488 virtual PRectangle GetDesiredRect()=0; 489 virtual int CaretFromEdge()=0; 490 virtual void Clear()=0; 491 virtual void Append(char *s, int type = -1)=0; 492 virtual int Length()=0; 493 virtual void Select(int n)=0; 494 virtual int GetSelection()=0; 495 virtual int Find(const char *prefix)=0; 496 virtual void GetValue(int n, char *value, int len)=0; 497 virtual void RegisterImage(int type, const char *xpm_data)=0; 498 virtual void RegisterRGBAImage(int type, int width, int height, const unsigned char *pixelsImage) = 0; 499 virtual void ClearRegisteredImages()=0; 500 virtual void SetDelegate(IListBoxDelegate *lbDelegate)=0; 501 virtual void SetList(const char* list, char separator, char typesep)=0; 502 }; 503 504 /** 505 * Menu management. 506 */ 507 class Menu { 508 MenuID mid; 509 public: 510 Menu() noexcept; GetID()511 MenuID GetID() const noexcept { return mid; } 512 void CreatePopUp(); 513 void Destroy(); 514 void Show(Point pt, Window &w); 515 }; 516 517 /** 518 * Dynamic Library (DLL/SO/...) loading 519 */ 520 class DynamicLibrary { 521 public: 522 virtual ~DynamicLibrary() = default; 523 524 /// @return Pointer to function "name", or NULL on failure. 525 virtual Function FindFunction(const char *name) = 0; 526 527 /// @return true if the library was loaded successfully. 528 virtual bool IsValid() = 0; 529 530 /// @return An instance of a DynamicLibrary subclass with "modulePath" loaded. 531 static DynamicLibrary *Load(const char *modulePath); 532 }; 533 534 #if defined(__clang__) 535 # if __has_feature(attribute_analyzer_noreturn) 536 # define CLANG_ANALYZER_NORETURN __attribute__((analyzer_noreturn)) 537 # else 538 # define CLANG_ANALYZER_NORETURN 539 # endif 540 #else 541 # define CLANG_ANALYZER_NORETURN 542 #endif 543 544 /** 545 * Platform class used to retrieve system wide parameters such as double click speed 546 * and chrome colour. Not a creatable object, more of a module with several functions. 547 */ 548 class Platform { 549 public: 550 Platform() = default; 551 Platform(const Platform &) = delete; 552 Platform(Platform &&) = delete; 553 Platform &operator=(const Platform &) = delete; 554 Platform &operator=(Platform &&) = delete; 555 ~Platform() = default; 556 static ColourDesired Chrome(); 557 static ColourDesired ChromeHighlight(); 558 static const char *DefaultFont(); 559 static int DefaultFontSize(); 560 static unsigned int DoubleClickTime(); 561 static void DebugDisplay(const char *s); LongFromTwoShorts(short a,short b)562 static constexpr long LongFromTwoShorts(short a,short b) noexcept { 563 return (a) | ((b) << 16); 564 } 565 566 static void DebugPrintf(const char *format, ...); 567 static bool ShowAssertionPopUps(bool assertionPopUps_); 568 static void Assert(const char *c, const char *file, int line) CLANG_ANALYZER_NORETURN; 569 }; 570 571 #ifdef NDEBUG 572 #define PLATFORM_ASSERT(c) ((void)0) 573 #else 574 #define PLATFORM_ASSERT(c) ((c) ? (void)(0) : Scintilla::Platform::Assert(#c, __FILE__, __LINE__)) 575 #endif 576 577 } 578 579 #endif 580