最近开始学习Linux编程,在Mate终端里试用了GDB的调试方式,对于习惯了用F5、F10和F11来调试的我来说,还真有点不习惯。于是我就把给Mate终端与GDB增加快捷键当作学习Linux编程的第一个实验目标来完成。现在我就把总结出来的方法分享给大家。
下载Mate终端源程序并解压缩:
链接: https://pan.baidu.com/s/1b8DCfkoHuKk0WSlKFXwVxQ密码: u5uu
里面有两个文件:
mate-terminal-1.21.0.tar.gz是原始源码包
mate-terminal-1.21.1.tar.xz是我改完的源码包
不想自己动手的的朋友可以下载我改过的包。编译安装方法在后面。
-
添加菜单
-
先将下面的菜单代码添加到src/terminal-window.c文件中的terminal_window_init函数,menu_entries数组,/* Terminal menu */段的前面。
/* Debugmenu */
{
"DebugProgram", NULL, N_("DebugProgram"), "F2",
NULL,
G_CALLBACK (debug_program_callback)
},
{
"DebugProcess", NULL,N_("Debug Process"), "F3",
NULL,
G_CALLBACK (debug_process_callback)
},
{
"DebugStart", NULL, N_("Debug Start"),"F4",
NULL,
G_CALLBACK (debug_start_callback)
},
{
"DebugContinue", NULL,N_("Debug Continue"), "F5",
NULL,
G_CALLBACK (debug_continue_callback)
},
{
"DebugNext", NULL, N_("Debug Next"),"F10",
NULL,
G_CALLBACK (debug_next_callback)
},
{
"DebugStep", NULL, N_("Debug Step"),"F11",
NULL,
G_CALLBACK (debug_step_callback)
},
再在/* Toplevel */段中的{ “Search”, NULL, N_(“_Search”) },下面加入
{ “Debug”, NULL, N_(“Debug”) },
-
将下面的菜单项添加到src/terminal.xml文件中的<menuaction="Terminal">段的前面。
-
打开po/ zh_CN.po文件,查找src/terminal-window.c段,将下面的字段添加到里面。
msgid"Debug"
msgstr"调试"
msgid"Debug Program"
msgstr"调试程序"
msgid"Debug Process"
msgstr"调试进程"
msgid"Debug Start"
msgstr"开始调试"
msgid"Debug Continue"
msgstr"继续执行"
msgid"Debug Next"
msgstr"单步执行"
msgid"Debug Step"
msgstr"进入函数"
msgid"Program Name"
msgstr"程序名称"
msgid"Name:"
msgstr"名称:"
msgid"Process Id"
msgstr"进程ID"
-
添加调用代码
-
将下面代码添加到/src/terminal-window.c文件中的terminal_window_init (TerminalWindow *window)函数前面。
staticvoid
terminal_get_program_name_dialog_response_cb(GtkWidget *dialog,
intresponse,
TerminalScreen *screen)
{
if (response == GTK_RESPONSE_OK)
{
GtkEntry *entry;
const gchar *gtext;
GString *gstr;
entry = GTK_ENTRY (g_object_get_data(G_OBJECT (dialog), "name-entry"));
gtext = gtk_entry_get_text (entry);
gstr = g_string_new(NULL);
gstr = g_string_assign(gstr,"gdb ");
g_string_append(gstr, gtext);
gstr = g_string_append_c(gstr,'\n');
vte_terminal_feed_child(screen,gstr->str, gstr->len);
g_string_free(gstr, TRUE);
}
gtk_widget_destroy (dialog);
}
staticvoid
terminal_get_program_id_dialog_response_cb(GtkWidget *dialog,
int response,
TerminalScreen *screen)
{
if (response == GTK_RESPONSE_OK)
{
GtkEntry *entry;
const gchar *gtext;
GString *gstr;
entry = GTK_ENTRY (g_object_get_data(G_OBJECT (dialog), "id-entry"));
gtext = gtk_entry_get_text (entry);
gstr = g_string_new(NULL);
gstr = g_string_assign(gstr,"gdb --pid ");
g_string_append(gstr, gtext);
gstr = g_string_append_c(gstr,'\n');
vte_terminal_feed_child(screen,gstr->str, gstr->len);
g_string_free(gstr, TRUE);
}
gtk_widget_destroy (dialog);
}
staticvoid
debug_program_callback(GtkAction *action,TerminalWindow *window)
{
TerminalWindowPrivate *priv =window->priv;
GtkWidget *dialog, *message_area, *hbox,*label, *entry;
if (priv->active_screen == NULL)
return;
dialog = gtk_message_dialog_new (GTK_WINDOW(window),
GTK_DIALOG_MODAL |GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_OTHER,
GTK_BUTTONS_OK_CANCEL,
"%s","");
gtk_window_set_title (GTK_WINDOW (dialog),_(“Program Name”));
gtk_window_set_resizable (GTK_WINDOW(dialog), FALSE);
gtk_window_set_role (GTK_WINDOW (dialog),“Program Name”);
gtk_dialog_set_default_response (GTK_DIALOG(dialog), GTK_RESPONSE_OK);
g_signal_connect (dialog,“response”,
G_CALLBACK(terminal_get_program_name_dialog_response_cb),
priv->active_screen);
g_signal_connect (dialog,“delete-event”,
G_CALLBACK(terminal_util_dialog_response_on_delete), NULL);
message_area =gtk_message_dialog_get_message_area
(GTK_MESSAGE_DIALOG(dialog));
gtk_container_foreach (
GTK_CONTAINER(message_area),
(GtkCallback)gtk_widget_hide,
NULL);
hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 12);
gtk_box_pack_start (GTK_BOX (message_area),hbox, FALSE, FALSE, 0);
label = gtk_label_new_with_mnemonic(_(“Name:”));
gtk_label_set_xalign (GTK_LABEL (label),0.0);
gtk_label_set_yalign (GTK_LABEL (label),0.5);
gtk_box_pack_start (GTK_BOX (hbox), label,FALSE, FALSE, 0);
entry = gtk_entry_new ();
gtk_entry_set_width_chars (GTK_ENTRY (entry),32);
gtk_entry_set_activates_default (GTK_ENTRY(entry), TRUE);
gtk_label_set_mnemonic_widget (GTK_LABEL(label), entry);
gtk_box_pack_start (GTK_BOX (hbox), entry,TRUE, TRUE, 0);
gtk_widget_show_all (hbox);
gtk_widget_grab_focus (entry);
g_object_set_data (G_OBJECT (dialog),"name-entry", entry);
gtk_window_present (GTK_WINDOW (dialog));
}
staticvoid
debug_process_callback(GtkAction *action,TerminalWindow *window)
{
TerminalWindowPrivate *priv =window->priv;
GtkWidget *dialog, *message_area, *hbox,*label, *entry;
if (priv->active_screen == NULL)
return;
dialog = gtk_message_dialog_new (GTK_WINDOW(window),
GTK_DIALOG_MODAL |GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_OTHER,
GTK_BUTTONS_OK_CANCEL,
"%s","");
gtk_window_set_title (GTK_WINDOW (dialog),_(“Process Id”));
gtk_window_set_resizable (GTK_WINDOW(dialog), FALSE);
gtk_window_set_role (GTK_WINDOW (dialog),“mate-terminal-change-title”);
gtk_dialog_set_default_response (GTK_DIALOG(dialog), GTK_RESPONSE_OK);
g_signal_connect (dialog,“response”,
G_CALLBACK(terminal_get_program_id_dialog_response_cb),
priv->active_screen);
g_signal_connect (dialog,“delete-event”,
G_CALLBACK(terminal_util_dialog_response_on_delete), NULL);
message_area =gtk_message_dialog_get_message_area
(GTK_MESSAGE_DIALOG(dialog));
gtk_container_foreach (
GTK_CONTAINER(message_area),
(GtkCallback)gtk_widget_hide,
NULL);
hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 12);
gtk_box_pack_start (GTK_BOX (message_area),hbox, FALSE, FALSE, 0);
label = gtk_label_new_with_mnemonic(_(“ID:”));
gtk_label_set_xalign (GTK_LABEL (label),0.0);
gtk_label_set_yalign (GTK_LABEL (label),0.5);
gtk_box_pack_start (GTK_BOX (hbox), label,FALSE, FALSE, 0);
entry = gtk_entry_new ();
gtk_entry_set_width_chars (GTK_ENTRY (entry),32);
gtk_entry_set_activates_default (GTK_ENTRY(entry), TRUE);
gtk_label_set_mnemonic_widget (GTK_LABEL(label), entry);
gtk_box_pack_start (GTK_BOX (hbox), entry,TRUE, TRUE, 0);
gtk_widget_show_all (hbox);
gtk_widget_grab_focus (entry);
g_object_set_data (G_OBJECT (dialog),"id-entry", entry);
gtk_window_present (GTK_WINDOW (dialog));
}
staticvoid
debug_start_callback(GtkAction *action,TerminalWindow *window)
{
GString *gstr;
gstr = g_string_new(NULL);
gstr = g_string_assign(gstr,“start\n”);
vte_terminal_feed_child(VTE_TERMINAL(window->priv->active_screen), gstr->str, gstr->len);
g_string_free(gstr, TRUE);
}
staticvoid
debug_continue_callback(GtkAction *action,TerminalWindow *window)
{
GString *gstr;
gstr = g_string_new(NULL);
gstr = g_string_assign(gstr,“c\n”);
vte_terminal_feed_child(VTE_TERMINAL(window->priv->active_screen), gstr->str, gstr->len);
g_string_free(gstr, TRUE);
}
staticvoid
debug_next_callback(GtkAction *action,TerminalWindow *window)
{
GString *gstr;
gstr = g_string_new(NULL);
gstr = g_string_assign(gstr,“n\n”);
vte_terminal_feed_child(VTE_TERMINAL(window->priv->active_screen), gstr->str, gstr->len);
g_string_free(gstr, TRUE);
}
staticvoid
debug_step_callback(GtkAction *action,TerminalWindow *window)
{
GString *gstr;
gstr = g_string_new(NULL);
gstr = g_string_assign(gstr,“s\n”);
vte_terminal_feed_child(VTE_TERMINAL(window->priv->active_screen), gstr->str, gstr->len);
g_string_free(gstr, TRUE);
}
-
本来这样就应该可以了,但试用发现F5、F10和F11这三个键与Mate终端的按键有冲突,不得不加入代码屏蔽掉原有的快捷键。代码如下,将它们添加到window_key_press_cb函数returnFALSE;语句之前。
elseif(event->keyval == GDK_KEY_F5)
{
TerminalWindow *window =TERMINAL_WINDOW (widget);
GString *gstr;
gstr = g_string_new(NULL);
gstr = g_string_assign(gstr,"c\n");
vte_terminal_feed_child(VTE_TERMINAL(window->priv->active_screen), gstr->str, gstr->len);
g_string_free(gstr, TRUE);
return TRUE;
}
else if(event->keyval == GDK_KEY_F10)
{
TerminalWindow *window =TERMINAL_WINDOW (widget);
GString *gstr;
gstr = g_string_new(NULL);
gstr = g_string_assign(gstr,"n\n");
vte_terminal_feed_child(VTE_TERMINAL(window->priv->active_screen), gstr->str, gstr->len);
g_string_free(gstr, TRUE);
return TRUE;
}
else if(event->keyval == GDK_KEY_F11)
{
TerminalWindow *window =TERMINAL_WINDOW (widget);
GString *gstr;
gstr = g_string_new(NULL);
gstr = g_string_assign(gstr,"s\n");
vte_terminal_feed_child(VTE_TERMINAL(window->priv->active_screen), gstr->str, gstr->len);
g_string_free(gstr, TRUE);
return TRUE;
}
编译安装
本例是在ubuntukylin-18.04-enhanced-amd64系统下进行的,如果你没有安装过mate-common和yelp-tools执行下面命令安装它们。
sudoapt-get install mate-common
sudoapt-get install yelp-tools
注意命令执行完后是否有错误提示,如果有重新执行它们即可解决。
安装依赖库,执行:
sudo apt-get install libglib2.0-dev
sudo apt-get installlibvte-2.91-dev
sudo apt-get installlibdconf-dev
安装Mate终端,执行:
./autogen.sh
make
sudomake install
安装完成。
添加好的菜单界面如下图: