#include "CtrlLib.h" namespace Upp { Size GetSmartTextSize(const char *text, Font font, int cx) { if(*text == '\1') { Size sz; RichText txt = ParseQTF(text + 1); txt.ApplyZoom(GetRichTextStdScreenZoom()); sz.cx = min(cx, txt.GetWidth()); sz.cy = txt.GetHeight(Zoom(1, 1), sz.cx); return sz; } return GetTLTextSize(ToUnicode(text, CHARSET_DEFAULT), font); } int GetSmartTextHeight(const char *s, int cx, Font font) { if(*s == '\1') { Size sz; RichText txt = ParseQTF(s + 1); txt.ApplyZoom(GetRichTextStdScreenZoom()); return txt.GetHeight(Zoom(1, 1), cx); } int cy = font.Info().GetHeight(); int h = cy; while(*s) { if(*s == '\n') h += cy; s++; } return h; } void DrawSmartText(Draw& draw, int x, int y, int cx, const char *text, Font font, Color ink, int accesskey, Color qtf_ink, int dark_theme) { if(*text == '\1') { RichText txt = ParseQTF(text + 1, accesskey); txt.ApplyZoom(GetRichTextStdScreenZoom()); PaintInfo pi; pi.darktheme = !IsNull(dark_theme) ? dark_theme : IsDarkTheme(); pi.textcolor = qtf_ink; txt.Paint(draw, x, y, cx, pi); return; } DrawTLText(draw, x, y, cx, ToUnicode(text, CHARSET_DEFAULT), font, ink, accesskey); } namespace detail { struct OriDraw : public DrawProxy { bool clockwise; Point origin; void Transform(int& x, int& y) const; void Transform(int& x, int& y, int& cx, int& cy) const; Event transform_point; Event transform_angle; Event transform_image; void OffsetOp(Point p) override; bool ClipOp(const Rect& r) override; bool ClipoffOp(const Rect& r) override; bool IsPaintingOp(const Rect& r) const override { return true; } void DrawRectOp(int x, int y, int cx, int cy, Color color) override; void DrawImageOp(int x, int y, int cx, int cy, const Image& img, const Rect& src, Color color) override; void DrawEllipseOp(const Rect& r, Color color, int pen, Color pencolor) override; void DrawTextOp(int x, int y, int angle, const wchar *text, Font font, Color ink, int n, const int *dx) override; }; force_inline void OriDraw::Transform(int& x, int& y) const { if(clockwise) { int y0 = y; y = origin.y + x; x = origin.x - y0; } else { int y0 = y; y = origin.y - x; x = origin.x + y0; } } force_inline void OriDraw::Transform(int& x, int& y, int& cx, int& cy) const { Transform(x, y); Swap(cx, cy); if(clockwise) x -= cx; else y -= cy; } void OriDraw::OffsetOp(Point p) { if(clockwise) ptr->OffsetOp(Point(-p.y, p.x)); else ptr->OffsetOp(Point(p.y, -p.x)); } bool OriDraw::ClipOp(const Rect& r) { Begin(); return true; } bool OriDraw::ClipoffOp(const Rect& r) { OffsetOp(r.TopLeft()); return true; } void OriDraw::DrawRectOp(int x, int y, int cx, int cy, Color color) { Transform(x, y, cx, cy); ptr->DrawRectOp(x, y, cx, cy, color); } void OriDraw::DrawImageOp(int x, int y, int cx, int cy, const Image& img, const Rect& src, Color color) { Transform(x, y, cx, cy); Image m = MakeImage(img, clockwise ? RotateClockwise : RotateAntiClockwise); ptr->DrawImageOp(x, y, cx, cy, m, Size(cx, cy), color); } void OriDraw::DrawEllipseOp(const Rect& r, Color color, int pen, Color pencolor) { int x = r.left; int y = r.top; int cx = r.GetWidth(); int cy = r.GetHeight(); Transform(x, y, cx, cy); ptr->DrawEllipseOp(RectC(x, y, cx, cy), color, pen, pencolor); } void OriDraw::DrawTextOp(int x, int y, int angle, const wchar *text, Font font, Color ink, int n, const int *dx) { Transform(x, y); if(clockwise) angle -= 900; else angle += 900; ptr->DrawTextOp(x, y, angle, text, font, ink, n, dx); } } void DrawSmartText(Draw& w, int x, int y, int cx, const char *text, int orientation, Font font, Color ink, int accesskey, Color qtf_ink, int dark_theme) { if(orientation == ORIENTATION_NORMAL) { DrawSmartText(w, x, y, cx, text, font, ink, accesskey, qtf_ink, dark_theme); return; } detail::OriDraw ow; ow.SetTarget(&w); ow.origin = Point(x, y); ow.clockwise = orientation == ORIENTATION_CLOCKWISE; DrawSmartText(ow, 0, 0, cx, text, font, ink, accesskey, qtf_ink, dark_theme); } String DeAmp(const char *s) { String out; for(; *s; out.Cat(*s++)) if(*s == '&') out.Cat('&'); return out; } bool CompareAccessKey(int accesskey, dword key) { return accesskey && dword(ToUpper(accesskey & 255) - 'A' + K_ALT_A) == key; } int ExtractAccessKey(const char *s, String& label) { byte akey = 0; int pos = 0; String text; bool qtf = *s == '\1'; while(*s) if((*s == '&' && !qtf || *s == '\b') && s[1] && s[1] != '&') { akey = ToAscii(ToUpper(s[1])); pos = text.GetLength() + 1; s++; } else text.Cat(*s++); text.Shrink(); label = text; return MAKELONG(akey, pos); } int ChooseAccessKey(const char *text, dword used) { for(const char *s = text; *s; s++) { byte ac = *s; if(ac < 128 && ac >= 'A' && ac <= 'Z' && (Ctrl::AccessKeyBit(ac) & used) == 0) return MAKELONG(ac, s - text + 1); } for(const char *s = text; *s; s++) { dword ac = ToUpper(*s); if(ac < 128 && ac >= 'A' && ac <= 'Z' && ac != 'I' && ac != 'L' && (Ctrl::AccessKeyBit(ac) & used) == 0) return ac; } for(const char *s = text; *s; s++) { dword ac = ToUpper(*s); if(ac < 128 && ac >= 'A' && ac <= 'Z' && (Ctrl::AccessKeyBit(ac) & used) == 0) return ac; } return 0; } }