最近开始学习Linux编程,在Mate终端里试用了GDB的调试方式,对于习惯了用F5、F10和F11来调试的我来说,还真有点不习惯。于是我就把给Mate终端与GDB增加快捷键当作学习Linux编程的第一个实验目标来完成。现在我就把总结出来的方法分享给大家。
下载Mate终端源程序并解压缩: 里面有两个文件: mate-terminal-1.21.0.tar.gz是原始源码包 mate-terminal-1.21.1.tar.xz是我改完的源码包 不想自己动手的的朋友可以下载我改过的包。编译安装方法在后面。 1. 添加菜单 1) 先将下面的菜单代码添加到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") }, 2) 将下面的菜单项添加到src/terminal.xml文件中的<menuaction="Terminal">段的前面。 <menu action="Debug"> <menuitem action="DebugProgram" /> <menuitem action="DebugProcess" /> <separator /> <menuitem action="DebugStart" /> <menuitem action="DebugContinue" /> <menuitem action="DebugNext" /> <menuitem action="DebugStep" /> </menu> 3) 打开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" 2. 添加调用代码 1) 将下面代码添加到/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); } 2) 本来这样就应该可以了,但试用发现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 安装完成。 添加好的菜单界面如下图:
|