From 08292bdeda70f9c4e4243a8672542cdd3830a7be Mon Sep 17 00:00:00 2001 From: Jaidyn Ann Date: Wed, 11 Aug 2021 16:28:13 -0500 Subject: [PATCH] (libinterface) Better URL-handling in UrlTextView --- libs/libinterface/UrlTextView.cpp | 58 +++++++++++++++++++++++++++---- libs/libinterface/UrlTextView.h | 8 ++++- 2 files changed, 58 insertions(+), 8 deletions(-) diff --git a/libs/libinterface/UrlTextView.cpp b/libs/libinterface/UrlTextView.cpp index 270c374..3246e05 100644 --- a/libs/libinterface/UrlTextView.cpp +++ b/libs/libinterface/UrlTextView.cpp @@ -5,6 +5,8 @@ #include "UrlTextView.h" +#include + #include #include #include @@ -101,7 +103,7 @@ UrlTextView::MouseDown(BPoint where) if ((buttons & B_PRIMARY_MOUSE_BUTTON) && OverUrl(where)) { fMouseDown = true; - BUrl url(WordAt(where)); + BUrl url = UrlAt(where); if (url.IsValid() == true) { fLastClicked = url; } @@ -239,6 +241,22 @@ UrlTextView::GetLine(int32 line) } +BUrl +UrlTextView::UrlAt(BPoint where) +{ + BString urlStr, line = GetLine(LineAt(where)); + BUrl url; + + int32 start; + int32 end; + if (_FindUrlString(line, &start, &end, 0) == true) { + line.CopyCharsInto(urlStr, start, end - start); + url.SetUrlString(urlStr); + } + return url; +} + + bool UrlTextView::OverText(BPoint where) { @@ -312,13 +330,39 @@ UrlTextView::_FindUrlString(BString text, int32* start, int32* end, int32 offset int32 urlOffset = text.FindFirst("://", offset); int32 urlStart = text.FindLast(" ", urlOffset) + 1; int32 urlEnd = text.FindFirst(" ", urlOffset); + + if (urlOffset == B_ERROR) + return false; + if (urlStart == B_ERROR) urlStart = 0; if (urlEnd == B_ERROR) urlEnd = text.CountChars(); - if (urlOffset != B_ERROR) { - *start = urlStart; - *end = urlEnd; - return true; - } - return false; + // Find first char of protocol + for (int32 i = urlStart; i < urlOffset; i++) + if (_IsValidUrlChar(text.ByteAt(i)) == true) { + urlStart = i; + break; + } + + // Find last char of URL + for (int32 i = urlOffset; i < urlEnd; i++) + if (_IsValidUrlChar(text.ByteAt(i)) == false) { + urlEnd = i; + break; + } + + *start = urlStart; + *end = urlEnd; + return true; +} + + +bool +UrlTextView::_IsValidUrlChar(char c) +{ + return (isalpha(c) || isdigit(c) || c == ':' || c == '%' || c == ':' + || c == '/' || c == '?' || c == '#' || c == '[' || c == ']' || c == '@' + || c == '!' || c == '$' || c == '&' || c == '(' || c == ')' || c == '*' + || c == '*' || c == '+' || c == ',' || c == ';' || c == '=' || c == '-' + || c == '.' || c == '_' || c == '~' || c == '\''); } diff --git a/libs/libinterface/UrlTextView.h b/libs/libinterface/UrlTextView.h index ead3814..21f4f42 100644 --- a/libs/libinterface/UrlTextView.h +++ b/libs/libinterface/UrlTextView.h @@ -28,7 +28,7 @@ public: virtual void Select(int32 startOffset, int32 endOffset); - // Only differs in that it changes font face and color of any URLs + // Only differs in that it changes font face and color of any URLs void Insert(const char* text, const text_run_array* runs = NULL); void SetText(const char* text, const text_run_array* runs = NULL); @@ -37,6 +37,8 @@ public: BString* _word = NULL); const char* GetLine(int32 line); + BUrl UrlAt(BPoint point); + bool OverText(BPoint where); bool OverUrl(BPoint where); @@ -46,7 +48,11 @@ private: bool _FindUrlString(BString text, int32* start, int32* end, int32 offset); + // Checks if char is allowed in a url, as per rfc3986 + bool _IsValidUrlChar(char c); + // For safe-keeping + text_run_array fNormalRun; text_run_array fUrlRun; BCursor* fUrlCursor;