Patch #3283 2012-04-28 02:57

alpha0010

Context menu: Open link in browser
Download
3283-Context_menu_O.patch (3.9 KB)
Category
Application::FeatureAdd
Status
Accepted
Close date
2012-06-17 07:52
Assigned to
ollydbg
Index: src/sdk/cbeditor.cpp
===================================================================
--- src/sdk/cbeditor.cpp    (revision 8021)
+++ src/sdk/cbeditor.cpp    (working copy)
@@ -552,6 +552,66 @@
         }
     }
 
+    wxString GetUrl()
+    {
+        cbStyledTextCtrl* control = m_pOwner->GetControl();
+        if (!control)
+            return wxEmptyString;
+
+        wxRegEx reUrl(wxT("***:(((ht|f)tp(s?)\\:\\/\\/)|(www\\.))(([a-zA-Z0-9\\-\\._]+(\\.[a-zA-Z0-9\\-\\._]+)+)|localhost)(\\/?)([a-zA-Z0-9\\-\\.\\?\\,\\'\\/\\\\\\+&%\\$#_]*)?([\\d\\w\\.\\/\\%\\+\\-\\=\\&\\?\\:\\\\\\"\\'\\,\\|\\~\\;]*)"));
+        wxString url = control->GetSelectedText();
+        // Is the URL selected?
+        if (reUrl.Matches(url))
+            return reUrl.GetMatch(url);
+        // else is there a URL near the cursor?
+
+        // Find out start position
+        int startPos = control->GetCurrentPos();
+        const wxString space = wxT(" \n\r\t{}");
+        wxChar curCh = control->GetCharAt(startPos);
+        while ( (startPos > 0) && (space.Find(curCh) == -1) )
+        {
+            startPos--;
+            curCh = control->GetCharAt(startPos);
+        }
+
+        // Find out end position
+        int endPos = control->GetCurrentPos();
+        int maxPos = control->GetLineEndPosition(control->GetLineCount());
+        curCh = control->GetCharAt(endPos);
+        while ( (endPos < maxPos) && (space.Find(curCh) == -1) )
+        {
+            endPos++;
+            curCh = control->GetCharAt(endPos);
+        }
+
+        url = control->GetTextRange(startPos, endPos);
+        if ( (control->GetLexer() == wxSCI_LEX_CPP)
+                && ( (control->GetStyleAt(control->GetCurrentPos()) == wxSCI_C_STRING)
+                     || (control->GetStyleAt(control->GetCurrentPos()) == wxSCI_C_STRINGEOL) ) )
+        {
+            url.Replace(wxT("\\n"), wxT("\n"));
+            url.Replace(wxT("\\r"), wxT("\r"));
+            url.Replace(wxT("\\t"), wxT("\t"));
+        }
+
+        if (reUrl.Matches(url))
+        {
+            wxString match = reUrl.GetMatch(url);
+            if ( (url.Find(match) + startPos < control->GetCurrentPos())
+                    && (url.Find(match) + startPos + (int)match.Length() > control->GetCurrentPos()) )
+            {
+                url = match;
+            }
+            else
+                url = wxEmptyString; // nope, too far from cursor, return invalid (empty)
+        }
+        else
+            url = wxEmptyString; // nope, return invalid (empty)
+
+        return url;
+    }
+
     //vars
     bool m_strip_trailing_spaces;
     bool m_ensure_final_line_end;
@@ -609,6 +669,7 @@
 const int idAddFileToProject = wxNewId();
 const int idRemoveFileFromProject = wxNewId();
 const int idShowFileInProject = wxNewId();
+const int idOpenUrl = wxNewId();
 
 const int idBookmarkAdd = wxNewId();
 const int idBookmarkRemove = wxNewId();
@@ -661,6 +722,7 @@
     EVT_MENU(idSplitHorz, cbEditor::OnContextMenuEntry)
     EVT_MENU(idSplitVert, cbEditor::OnContextMenuEntry)
     EVT_MENU(idUnsplit, cbEditor::OnContextMenuEntry)
+    EVT_MENU(idOpenUrl, cbEditor::OnContextMenuEntry)
 
     EVT_SCI_ZOOM(-1, cbEditor::OnZoom)
     EVT_SCI_ZOOM(-1, cbEditor::OnZoom)
@@ -2673,6 +2735,12 @@
     }
     else
     {
+        if(!noeditor && !m_pData->GetUrl().IsEmpty())
+        {
+            popup->InsertSeparator(0);
+            popup->Insert(0, idOpenUrl, _("Open link in browser"));
+        }
+
         wxMenu* splitMenu = new wxMenu;
         splitMenu->Append(idSplitHorz, _("Horizontally"));
         splitMenu->Append(idSplitVert, _("Vertically"));
@@ -2933,6 +3001,8 @@
         UnfoldBlockFromLine();
     else if (id == idFoldingToggleCurrent)
         ToggleFoldBlockFromLine();
+    else if (id == idOpenUrl)
+        wxLaunchDefaultBrowser(m_pData->GetUrl());
     else if (id == idSplitHorz)
         Split(stHorizontal);
     else if (id == idSplitVert)
ollydbg 2012-04-28 07:59

Very nice feature, I would like to apply in the near future.

alpha0010 2012-05-26 20:11

Improve detection accuracy on escape sequences in strings.

mortenmacfly 2012-05-27 08:40

Agreed from my side. Its like in Eclipse or other editors...

Just do a tiny clean-up of the code, for example: if you checked that url.IsEmpty() you don't need the last else- clause where you set url to "empty" explicitly again...

mortenmacfly 2012-05-27 09:03
Another one: It does not compile under wxWidgets 2.9.x.

I've an updated function here, that works (and is cleaned-up):

    wxString GetUrl()
    {
        cbStyledTextCtrl* control = m_pOwner->GetControl();
        if (!control)
            return wxEmptyString;

        wxRegEx reUrl(wxT("***:(((ht|f)tp(s?)\\:\\/\\/)|(www\\.))(([a-zA-Z0-9\\-\\._]+(\\.[a-zA-Z0-9\\-\\._]+)+)|localhost)(\\/?)([a-zA-Z0-9\\-\\.\\?\\,\\'\\/\\\\\\+&amp;%\\$#_]*)?([\\d\\w\\.\\/\\%\\+\\-\\=\\&amp;\\?\\:\\\\\\&quot;\\'\\,\\|\\~\\;]*)"));
        wxString url = control->GetSelectedText(); url.Trim(true).Trim(false);
        if (url.IsEmpty())
            return wxEmptyString;
        if (reUrl.Matches(url))
            return reUrl.GetMatch(url);

        // Find out start position
        int startPos = control->GetCurrentPos();
        const wxString space = wxT(" \n\r\t{}");
        wxChar startCh = control->GetCharAt(startPos);
        while ( (startPos > 0) && (space.Find(startCh) == -1) )
            startPos--;

        // Find out end position
        int endPos = control->GetCurrentPos();
        int maxPos = control->GetLineEndPosition(control->GetLineCount());
        wxChar endCh = control->GetCharAt(endPos);
        while ( (endPos < maxPos) && (space.Find(endCh) == -1) )
            endPos++;

        url = control->GetTextRange(startPos, endPos);
        if (    (control->GetLexer() == wxSCI_LEX_CPP)
            &&  (   (control->GetStyleAt(control->GetCurrentPos()) == wxSCI_C_STRING)
                 || (control->GetStyleAt(control->GetCurrentPos()) == wxSCI_C_STRINGEOL) ) )
        {
            url.Replace(wxT("\\n"), wxT("\n"));
            url.Replace(wxT("\\r"), wxT("\r"));
            url.Replace(wxT("\\t"), wxT("\t"));
        }

        if (reUrl.Matches(url))
        {
            wxString match = reUrl.GetMatch(url);
            if (   (url.Find(match) + startPos                       < control->GetCurrentPos())
                && (url.Find(match) + startPos + (int)match.Length() > control->GetCurrentPos()) )
            {
                url = match;
            }
            else
                url = wxEmptyString; // nope, return invalid (empty)
        }
        else
            url = wxEmptyString; // nope, return invalid (empty)

        return url;
    }
alpha0010 2012-05-27 22:03

Updated to the cleaned-up function with the following modifications:

* removed Trim() - had no purpose

* removed several optimizations - these caused it to only work if the URL was already selected (GetUrl() first checks if a URL is selected, then checks if there is a URL near the cursor - so one can simply right-click on a link, without needing to actually select it)

mortenmacfly 2012-06-01 16:00
This part:

        while ( (startPos > 0) && (space.Find(control->GetCharAt(startPos)) == -1) )

does NOT work with wx2.9.x. I changed that on purpose to:

        wxChar startCh = control->GetCharAt(startPos);
        while ( (startPos > 0) && (space.Find(startCh) == -1) )
            startPos--;

...(at two positions) in my other comment. Please leave it like that.
alpha0010 2012-06-01 21:11

Apologies; I had reverted that because it broke the range finding logic (wxChar must update each iteration).

Does this revision compile with wx2.9.x?

mortenmacfly 2012-06-16 07:33

Ok, this one is fine.

@ollydbg: Should I commit / will you? (I have it aligned a little bit more, but the content is the same and working in this version.)

ollydbg 2012-06-17 01:46

@morten: please commit it.

PS: I see there are some parenthesis in "if" or "while" condition which can be removed, right?

mortenmacfly 2012-06-17 07:52

Applied in SVN head (on behalf of ollydbg). Thanks!