<p>Hum, I don't really like the popup, esp. because it can popup far from the pointer or whatever the trigger was (and it be something else?).  Also, the popup sizing is incorrect (at least with my theme, so it's incorrect in general, yet maybe happen to be good in your case).  This is fixable correctly (not like in Scintilla), but not really trivial.</p>

<p>Anyway, I wanted to check if it was easy to implement using AUTOCLISTs, and realized Scintilla had USERLISTs, which sounded quite nice :)<br>
Here is a sample of how it might look like (yet it has 2 unresolved issues, one hard and one simple):</p>

<div class="highlight highlight-source-c"><pre><span class="pl-k">static</span> <span class="pl-k">void</span> <span class="pl-en">on_goto_popup_sci_notify</span>(GtkWidget *sci, gint scn, SCNotification *nt, gpointer data)
{
    <span class="pl-k">switch</span> (nt->nmhdr.<span class="pl-smi">code</span>)
    {
        <span class="pl-k">case</span> SCN_USERLISTSELECTION:
            <span class="pl-k">if</span> (nt->listType == <span class="pl-c1">42</span>)
            {
                gchar *name = <span class="pl-c1">g_strdup</span>(nt->text);
                gchar *line = <span class="pl-c1">strrchr</span>(name, <span class="pl-s"><span class="pl-pds">'</span>:<span class="pl-pds">'</span></span>);
                GeanyDocument *old_doc = <span class="pl-c1">document_get_current</span>();
                GeanyDocument *new_doc;

                <span class="pl-k">if</span> (line)
                {
                    *line = <span class="pl-c1">0</span>;
                    line++;
                }

                new_doc = <span class="pl-c1">document_find_by_real_path</span>(name);
                <span class="pl-k">if</span> (!new_doc)
                    new_doc = <span class="pl-c1">document_open_file</span>(name, <span class="pl-c1">FALSE</span>, <span class="pl-c1">NULL</span>, <span class="pl-c1">NULL</span>);

                <span class="pl-k">if</span> (new_doc)
                    <span class="pl-c1">navqueue_goto_line</span>(old_doc, new_doc, line ? <span class="pl-c1">atoi</span>(line) : <span class="pl-c1">0</span>);

                <span class="pl-c1">g_free</span>(name);
            }
            <span class="pl-c">/* fallthrough */</span>
        <span class="pl-k">case</span> SCN_AUTOCCANCELLED:
            <span class="pl-c1">g_signal_handlers_disconnect_by_func</span>(sci, on_goto_popup_sci_notify, data);
            <span class="pl-k">break</span>;
    }
}


<span class="pl-k">static</span> <span class="pl-k">void</span> <span class="pl-en">show_goto_popup</span>(GeanyDocument *doc, GPtrArray *tags, gboolean have_best)
{
    TMTag *tmtag;
    guint i;
    GString *words;

    <span class="pl-k">if</span> (tags->len < <span class="pl-c1">1</span>)
        <span class="pl-k">return</span>;

    words = <span class="pl-c1">g_string_new</span>(<span class="pl-c1">NULL</span>);

    <span class="pl-c1">foreach_ptr_array</span>(tmtag, i, tags)
    {
        <span class="pl-k">if</span> (words->len > <span class="pl-c1">0</span>)
            <span class="pl-c1">g_string_append_c</span>(words, <span class="pl-s"><span class="pl-pds">'</span><span class="pl-cce">\n</span><span class="pl-pds">'</span></span>);

        <span class="pl-c">/* FIXME: how to show something and get associated data? */</span>
        <span class="pl-c1">g_string_append_printf</span>(words, <span class="pl-s"><span class="pl-pds">"</span><span class="pl-c1">%s</span>:<span class="pl-c1">%lu</span><span class="pl-pds">"</span></span>, tmtag->file->file_name, tmtag->line);

        <span class="pl-c">/* FIXME: better images */</span>
        <span class="pl-k">if</span> (!<span class="pl-c1">EMPTY</span>(tmtag->arglist))
            <span class="pl-c1">g_string_append</span>(words, <span class="pl-s"><span class="pl-pds">"</span>?2<span class="pl-pds">"</span></span>);
        <span class="pl-k">else</span>
            <span class="pl-c1">g_string_append</span>(words, <span class="pl-s"><span class="pl-pds">"</span>?1<span class="pl-pds">"</span></span>);
    }

    <span class="pl-c1">g_signal_connect</span>(doc->editor->sci, <span class="pl-s"><span class="pl-pds">"</span>sci-notify<span class="pl-pds">"</span></span>, <span class="pl-c1">G_CALLBACK</span>(on_goto_popup_sci_notify), <span class="pl-c1">NULL</span>);
    <span class="pl-c1">scintilla_send_message</span>(doc->editor->sci, SCI_AUTOCCANCEL, <span class="pl-c1">0</span>, <span class="pl-c1">0</span>);
    <span class="pl-c1">scintilla_send_message</span>(doc->editor->sci, SCI_USERLISTSHOW, <span class="pl-c1">42</span>, (<span class="pl-c1">sptr_t</span>) words->str);
    <span class="pl-c1">g_string_free</span>(words, <span class="pl-c1">TRUE</span>);
}</pre></div>

<p>It's quick'n dirty, and we might rather want to register that in the editor handler or somewhere -- although this doesn't feel <em>so</em> bad in the end, as it's contained and temporary.  The real question here is the first *FIXME in the code, e.g. whether it's possible to store some additional data with the displayed entry.  Otherwise, we either need something like I did, or a table mapping the name to the actual tag… meh.</p>

<hr>

<p>Apart that, I don't know, the theory is probably fine, but to really have an opinion I'd need to use it for some time and see in the "long" run.<br>
And there's an issue when merging this in current master, conflicting signature for <code>tm_workspace_find()</code>.  And an int should be unsigned :)</p>

<div class="highlight highlight-source-diff"><pre><span class="pl-c1">diff --git a/src/symbols.c b/src/symbols.c</span>
index ed71004..7e429ec 100644
<span class="pl-md">--- a/src/symbols.c</span>
<span class="pl-mi1">+++ b/src/symbols.c</span>
<span class="pl-mdr">@@ -1990,7 +1990,7 @@</span> static void show_goto_popup(GPtrArray *tags, gboolean have_best)
     GtkTreeModel *model;
     GtkTreeIter iter;
     TMTag *tmtag;
<span class="pl-md">-    gint i;</span>
<span class="pl-mi1">+    guint i;</span>

     if (!tag_goto_popup)
         create_goto_popup();
<span class="pl-mdr">@@ -2094,7 +2094,7 @@</span> static gboolean goto_tag(const gchar *name, gboolean definition)

     /* goto tag definition: all except prototypes / forward declarations / externs */
     type = (definition) ? tm_tag_max_t - forward_types : forward_types;
<span class="pl-md">-    all_tags = tm_workspace_find(name, type, NULL, FALSE, old_doc->file_type->lang);</span>
<span class="pl-mi1">+    all_tags = tm_workspace_find(name, NULL, type, NULL, old_doc->file_type->lang);</span>

     /* get rid of global tags */
     workspace_tags = g_ptr_array_new();</pre></div>

<p>(the <code>tm_workspace_find()</code> might not be correctly fixed, I did that quickly and I'm not yet familiar with the new API)</p>

<p style="font-size:small;-webkit-text-size-adjust:none;color:#666;">—<br>Reply to this email directly or <a href="https://github.com/geany/geany/pull/406#issuecomment-183763414">view it on GitHub</a>.<img alt="" height="1" src="https://github.com/notifications/beacon/ABDrJ2TZ1m12qz1-d7-MtHFC1XktMAsKks5pj52hgaJpZM4DUzez.gif" width="1" /></p>
<div itemscope itemtype="http://schema.org/EmailMessage">
<div itemprop="action" itemscope itemtype="http://schema.org/ViewAction">
  <link itemprop="url" href="https://github.com/geany/geany/pull/406#issuecomment-183763414"></link>
  <meta itemprop="name" content="View Pull Request"></meta>
</div>
<meta itemprop="description" content="View this Pull Request on GitHub"></meta>
</div>