242 lines
7.4 KiB
C
242 lines
7.4 KiB
C
/* ide-debugger-actions.c
|
|
*
|
|
* Copyright 2017-2019 Christian Hergert <chergert@redhat.com>
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
*/
|
|
|
|
#define G_LOG_DOMAIN "ide-debugger-actions"
|
|
|
|
#include "config.h"
|
|
|
|
#include "ide-debugger-private.h"
|
|
|
|
typedef struct _IdeDebuggerActionEntry IdeDebuggerActionEntry;
|
|
|
|
typedef void (*IdeDebuggerActionHandler) (IdeDebugger *debugger,
|
|
const IdeDebuggerActionEntry *entry,
|
|
GVariant *param);
|
|
|
|
struct _IdeDebuggerActionEntry
|
|
{
|
|
const gchar *action_name;
|
|
IdeDebuggerActionHandler handler;
|
|
gint movement;
|
|
gint running_state;
|
|
};
|
|
|
|
enum {
|
|
RUNNING_STARTED = 1,
|
|
RUNNING_NOT_STARTED = 1 << 1,
|
|
RUNNING_ACTIVE = 1 << 2,
|
|
RUNNING_NOT_ACTIVE = 1 << 3,
|
|
};
|
|
|
|
static gboolean
|
|
check_running_state (IdeDebugger *self,
|
|
gint state)
|
|
{
|
|
if (state & RUNNING_STARTED)
|
|
{
|
|
if (!_ide_debugger_get_has_started (self))
|
|
return FALSE;
|
|
}
|
|
|
|
if (state & RUNNING_NOT_STARTED)
|
|
{
|
|
if (_ide_debugger_get_has_started (self))
|
|
return FALSE;
|
|
}
|
|
|
|
if (state & RUNNING_ACTIVE)
|
|
{
|
|
if (!ide_debugger_get_is_running (self))
|
|
return FALSE;
|
|
}
|
|
|
|
if (state & RUNNING_NOT_ACTIVE)
|
|
{
|
|
if (ide_debugger_get_is_running (self))
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
ide_debugger_actions_movement (IdeDebugger *self,
|
|
const IdeDebuggerActionEntry *entry,
|
|
GVariant *param)
|
|
{
|
|
g_assert (IDE_IS_DEBUGGER (self));
|
|
g_assert (entry != NULL);
|
|
|
|
ide_debugger_move_async (self, entry->movement, NULL, NULL, NULL);
|
|
}
|
|
|
|
static void
|
|
ide_debugger_actions_stop (IdeDebugger *self,
|
|
const IdeDebuggerActionEntry *entry,
|
|
GVariant *param)
|
|
{
|
|
g_assert (IDE_IS_DEBUGGER (self));
|
|
g_assert (entry != NULL);
|
|
|
|
ide_debugger_interrupt_async (self, NULL, NULL, NULL, NULL);
|
|
}
|
|
|
|
static void
|
|
ide_debugger_actions_clear_breakpoints (IdeDebugger *self,
|
|
const IdeDebuggerActionEntry *entry,
|
|
GVariant *param)
|
|
{
|
|
g_autoptr (GPtrArray) breakpoints = NULL;
|
|
GListModel *breakpoint_list_model;
|
|
guint n_elements;
|
|
|
|
g_assert (IDE_IS_DEBUGGER (self));
|
|
g_assert (entry != NULL);
|
|
|
|
breakpoint_list_model = ide_debugger_get_breakpoints (self);
|
|
n_elements = g_list_model_get_n_items (breakpoint_list_model);
|
|
g_debug ("Number of breakpoints: %d", n_elements);
|
|
|
|
breakpoints = g_ptr_array_new_with_free_func (g_object_unref);
|
|
|
|
for (guint i = 0; i < n_elements; i++)
|
|
{
|
|
g_ptr_array_add (breakpoints, g_list_model_get_item (breakpoint_list_model, i));
|
|
}
|
|
|
|
for (guint i = 0; i < n_elements; i++)
|
|
{
|
|
ide_debugger_remove_breakpoint_async (self, g_ptr_array_index (breakpoints, i),
|
|
NULL, NULL, NULL);
|
|
}
|
|
}
|
|
|
|
static IdeDebuggerActionEntry action_info[] = {
|
|
{ "start", ide_debugger_actions_movement, IDE_DEBUGGER_MOVEMENT_START, RUNNING_NOT_STARTED },
|
|
{ "stop", ide_debugger_actions_stop, -1, RUNNING_STARTED | RUNNING_ACTIVE },
|
|
{ "continue", ide_debugger_actions_movement, IDE_DEBUGGER_MOVEMENT_CONTINUE, RUNNING_STARTED | RUNNING_NOT_ACTIVE },
|
|
{ "step-in", ide_debugger_actions_movement, IDE_DEBUGGER_MOVEMENT_STEP_IN, RUNNING_STARTED | RUNNING_NOT_ACTIVE },
|
|
{ "step-over", ide_debugger_actions_movement, IDE_DEBUGGER_MOVEMENT_STEP_OVER, RUNNING_STARTED | RUNNING_NOT_ACTIVE },
|
|
{ "finish", ide_debugger_actions_movement, IDE_DEBUGGER_MOVEMENT_FINISH, RUNNING_STARTED | RUNNING_NOT_ACTIVE },
|
|
{ "clear-breakpoints", ide_debugger_actions_clear_breakpoints, -1, RUNNING_STARTED | RUNNING_NOT_ACTIVE },
|
|
};
|
|
|
|
static gboolean
|
|
ide_debugger_get_action_enabled (GActionGroup *group,
|
|
const gchar *action_name)
|
|
{
|
|
IdeDebugger *self = IDE_DEBUGGER (group);
|
|
|
|
for (guint i = 0; i < G_N_ELEMENTS (action_info); i++)
|
|
{
|
|
const IdeDebuggerActionEntry *entry = &action_info[i];
|
|
if (g_strcmp0 (entry->action_name, action_name) == 0)
|
|
return check_running_state (self, entry->running_state);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void
|
|
_ide_debugger_update_actions (IdeDebugger *self)
|
|
{
|
|
g_assert (IDE_IS_DEBUGGER (self));
|
|
|
|
for (guint i = 0; i < G_N_ELEMENTS (action_info); i++)
|
|
{
|
|
const IdeDebuggerActionEntry *entry = &action_info[i];
|
|
gboolean enabled;
|
|
|
|
enabled = ide_debugger_get_action_enabled (G_ACTION_GROUP (self), entry->action_name);
|
|
g_action_group_action_enabled_changed (G_ACTION_GROUP (self), entry->action_name, enabled);
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
ide_debugger_has_action (GActionGroup *group,
|
|
const gchar *action_name)
|
|
{
|
|
g_assert (IDE_IS_DEBUGGER (group));
|
|
g_assert (action_name != NULL);
|
|
|
|
for (guint i = 0; i < G_N_ELEMENTS (action_info); i++)
|
|
{
|
|
const IdeDebuggerActionEntry *entry = &action_info[i];
|
|
|
|
if (g_strcmp0 (action_name, entry->action_name) == 0)
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static gchar **
|
|
ide_debugger_list_actions (GActionGroup *group)
|
|
{
|
|
GPtrArray *ar = g_ptr_array_new ();
|
|
|
|
for (guint i = 0; i < G_N_ELEMENTS (action_info); i++)
|
|
g_ptr_array_add (ar, g_strdup (action_info[i].action_name));
|
|
g_ptr_array_add (ar, NULL);
|
|
|
|
return (gchar **)g_ptr_array_free (ar, FALSE);
|
|
}
|
|
|
|
static gpointer
|
|
null_return_func (void)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
ide_debugger_activate_action (GActionGroup *group,
|
|
const gchar *action_name,
|
|
GVariant *parameter)
|
|
{
|
|
IdeDebugger *self = IDE_DEBUGGER (group);
|
|
|
|
g_assert (IDE_IS_DEBUGGER (self));
|
|
g_assert (action_name != NULL);
|
|
|
|
for (guint i = 0; i < G_N_ELEMENTS (action_info); i++)
|
|
{
|
|
const IdeDebuggerActionEntry *entry = &action_info[i];
|
|
|
|
if (g_strcmp0 (entry->action_name, action_name) == 0)
|
|
{
|
|
entry->handler (self, entry, parameter);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
_ide_debugger_class_init_actions (GActionGroupInterface *iface)
|
|
{
|
|
iface->has_action = ide_debugger_has_action;
|
|
iface->list_actions = ide_debugger_list_actions;
|
|
iface->get_action_enabled = ide_debugger_get_action_enabled;
|
|
iface->activate_action = ide_debugger_activate_action;
|
|
iface->get_action_parameter_type = (gpointer)null_return_func;
|
|
iface->get_action_state_type = (gpointer)null_return_func;
|
|
iface->get_action_state_hint = (gpointer)null_return_func;
|
|
iface->get_action_state = (gpointer)null_return_func;
|
|
}
|