pcsxr-1.9.92
[pcsx_rearmed.git] / gui / Cheat.c
1 /*  Cheat Support for PCSX-Reloaded
2  *  Copyright (C) 2009, Wei Mingzhi <whistler_wmz@users.sf.net>.
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA
17  */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <stdint.h>
23
24 #include <gdk/gdkkeysyms.h>
25 #include <gtk/gtk.h>
26 #include <glade/glade.h>
27
28 #include "Linux.h"
29
30 #include "../libpcsxcore/cheat.h"
31 #include "../libpcsxcore/psxmem.h"
32
33 GtkWidget *CheatListDlg = NULL;
34 GtkWidget *CheatSearchDlg = NULL;
35
36 static void LoadCheatListItems(int index) {
37         GtkListStore *store = gtk_list_store_new(2, G_TYPE_BOOLEAN, G_TYPE_STRING);
38         GtkTreeIter iter;
39         GtkWidget *widget;
40         GladeXML *xml;
41
42         int i;
43
44         xml = glade_get_widget_tree(CheatListDlg);
45         widget = glade_xml_get_widget(xml, "GtkCList_Cheat");
46
47         for (i = 0; i < NumCheats; i++) {
48                 gtk_list_store_append(store, &iter);
49                 gtk_list_store_set(store, &iter, 0, Cheats[i].Enabled, 1, Cheats[i].Descr, -1);
50         }
51
52         gtk_tree_view_set_model(GTK_TREE_VIEW(widget), GTK_TREE_MODEL(store));
53         g_object_unref(G_OBJECT(store));
54         gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(widget), TRUE);
55         gtk_widget_show(widget);
56
57         if (index >= NumCheats) {
58                 index = NumCheats - 1;
59         }
60
61         if (index >= 0) {
62                 GtkTreePath *path;
63                 GtkTreeSelection *sel;
64
65                 path = gtk_tree_path_new_from_indices(index, -1);
66                 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
67
68                 gtk_tree_selection_select_path(sel, path);
69                 gtk_tree_path_free(path);
70         }
71 }
72
73 static void CheatList_TreeSelectionChanged(GtkTreeSelection *selection, gpointer user_data) {
74         GladeXML *xml;
75         GtkTreeIter iter;
76         GtkTreeModel *model;
77         GtkTreePath *path;
78
79         gboolean selected;
80         int i;
81
82         selected = gtk_tree_selection_get_selected(selection, &model, &iter);
83
84         if (selected) {
85                 path = gtk_tree_model_get_path(model, &iter);
86                 i = *gtk_tree_path_get_indices(path);
87                 gtk_tree_path_free(path);
88
89                 // If a row was selected, and the row is not blank, we can now enable
90                 // some of the disabled widgets
91                 xml = glade_get_widget_tree(CheatListDlg);
92
93                 gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "editbutton1")), TRUE);
94                 gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "delbutton1")), TRUE);
95         } else {
96                 xml = glade_get_widget_tree(CheatListDlg);
97
98                 gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "editbutton1")), FALSE);
99                 gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "delbutton1")), FALSE);
100         }
101
102         gtk_widget_set_sensitive (GTK_WIDGET(glade_xml_get_widget(xml, "savebutton1")), NumCheats);
103 }
104
105 static void OnCheatListDlg_AddClicked(GtkWidget *widget, gpointer user_data) {
106         GtkWidget *dlg;
107         GtkWidget *box, *scroll, *label, *descr_edit, *code_edit;
108
109         dlg = gtk_dialog_new_with_buttons(_("Add New Cheat"), GTK_WINDOW(CheatListDlg),
110                 GTK_DIALOG_MODAL, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
111                 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL);
112
113         gtk_window_set_default_size(GTK_WINDOW(dlg), 350, 350);
114
115         box = GTK_WIDGET(GTK_DIALOG(dlg)->vbox);
116
117         label = gtk_label_new(_("Cheat Description:"));
118         gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 5);
119         gtk_widget_show(label);
120
121         descr_edit = gtk_entry_new();
122         gtk_box_pack_start(GTK_BOX(box), descr_edit, FALSE, FALSE, 5);
123         gtk_widget_show(descr_edit);
124
125         label = gtk_label_new(_("Cheat Code:"));
126         gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 5);
127         gtk_widget_show(label);
128
129         code_edit = gtk_text_view_new();
130         gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(code_edit), GTK_WRAP_CHAR);
131
132         scroll = gtk_scrolled_window_new(NULL, NULL);
133         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll),
134                 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
135
136         gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll), code_edit);
137         gtk_widget_show(code_edit);
138
139         gtk_box_pack_start(GTK_BOX(box), scroll, TRUE, TRUE, 5);
140         gtk_widget_show(scroll);
141
142         gtk_window_set_position(GTK_WINDOW(dlg), GTK_WIN_POS_CENTER);
143
144         gtk_widget_show_all(dlg);
145
146         if (gtk_dialog_run(GTK_DIALOG(dlg)) == GTK_RESPONSE_ACCEPT) {
147                 GtkTextBuffer *b = gtk_text_view_get_buffer(GTK_TEXT_VIEW(code_edit));
148                 GtkTextIter s, e;
149                 char *codetext;
150
151                 gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(b), &s, &e);
152                 codetext = strdup(gtk_text_buffer_get_text(GTK_TEXT_BUFFER(b), &s, &e, FALSE));
153
154                 if (AddCheat(gtk_entry_get_text(GTK_ENTRY(descr_edit)), codetext) != 0) {
155                         SysErrorMessage(_("Error"), _("Invalid cheat code!"));
156                 }
157
158                 LoadCheatListItems(NumCheats - 1);
159
160                 free(codetext);
161         }
162
163         gtk_widget_destroy(dlg);
164 }
165
166 static void OnCheatListDlg_EditClicked(GtkWidget *widget, gpointer user_data) {
167         GtkWidget *dlg;
168         GtkWidget *box, *scroll, *label, *descr_edit, *code_edit;
169         GladeXML *xml;
170         GtkTreeIter iter;
171         GtkTreeModel *model;
172         GtkTreePath *path;
173
174         gboolean selected;
175         int index, i;
176         char buf[8192];
177         char *p = buf;
178
179         xml = glade_get_widget_tree(CheatListDlg);
180         widget = glade_xml_get_widget(xml, "GtkCList_Cheat");
181
182         selected = gtk_tree_selection_get_selected(
183                 gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)),
184                 &model, &iter);
185
186         if (!selected) {
187                 return;
188         }
189
190         path = gtk_tree_model_get_path(model, &iter);
191         index = *gtk_tree_path_get_indices(path);
192         gtk_tree_path_free(path);
193
194         dlg = gtk_dialog_new_with_buttons(_("Edit Cheat"), GTK_WINDOW(CheatListDlg),
195                 GTK_DIALOG_MODAL, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
196                 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL);
197
198         gtk_window_set_default_size(GTK_WINDOW(dlg), 350, 350);
199
200         box = GTK_WIDGET(GTK_DIALOG(dlg)->vbox);
201
202         label = gtk_label_new(_("Cheat Description:"));
203         gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 5);
204         gtk_widget_show(label);
205
206         descr_edit = gtk_entry_new();
207         gtk_entry_set_text(GTK_ENTRY(descr_edit), Cheats[index].Descr);
208         gtk_box_pack_start(GTK_BOX(box), descr_edit, FALSE, FALSE, 5);
209         gtk_widget_show(descr_edit);
210
211         label = gtk_label_new(_("Cheat Code:"));
212         gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 5);
213         gtk_widget_show(label);
214
215         code_edit = gtk_text_view_new();
216
217         for (i = Cheats[index].First; i < Cheats[index].First + Cheats[index].n; i++) {
218                 sprintf(p, "%.8X %.4X\n", CheatCodes[i].Addr, CheatCodes[i].Val);
219                 p += 14;
220                 *p = '\0';
221         }
222
223         gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(code_edit)),
224                 buf, -1);
225
226         gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(code_edit), GTK_WRAP_CHAR);
227
228         scroll = gtk_scrolled_window_new(NULL, NULL);
229         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll),
230                 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
231
232         gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll), code_edit);
233         gtk_widget_show(code_edit);
234
235         gtk_box_pack_start(GTK_BOX(box), scroll, TRUE, TRUE, 5);
236         gtk_widget_show(scroll);
237
238         gtk_window_set_position(GTK_WINDOW(dlg), GTK_WIN_POS_CENTER);
239
240         gtk_widget_show_all(dlg);
241
242         if (gtk_dialog_run(GTK_DIALOG(dlg)) == GTK_RESPONSE_ACCEPT) {
243                 GtkTextBuffer *b = gtk_text_view_get_buffer(GTK_TEXT_VIEW(code_edit));
244                 GtkTextIter s, e;
245                 char *codetext;
246
247                 gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(b), &s, &e);
248                 codetext = strdup(gtk_text_buffer_get_text(GTK_TEXT_BUFFER(b), &s, &e, FALSE));
249
250                 if (EditCheat(index, gtk_entry_get_text(GTK_ENTRY(descr_edit)), codetext) != 0) {
251                         SysErrorMessage(_("Error"), _("Invalid cheat code!"));
252                 }
253
254                 LoadCheatListItems(index);
255
256                 free(codetext);         
257         }
258
259         gtk_widget_destroy(dlg);
260 }
261
262 static void OnCheatListDlg_DelClicked(GtkWidget *widget, gpointer user_data) {
263         GladeXML *xml;
264         GtkTreeIter iter;
265         GtkTreeModel *model;
266         GtkTreePath *path;
267
268         gboolean selected;
269         int i = -1;
270
271         xml = glade_get_widget_tree(CheatListDlg);
272         widget = glade_xml_get_widget(xml, "GtkCList_Cheat");
273
274         selected = gtk_tree_selection_get_selected(
275                 gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)),
276                 &model, &iter);
277
278         if (selected) {
279                 path = gtk_tree_model_get_path(model, &iter);
280                 i = *gtk_tree_path_get_indices(path);
281                 gtk_tree_path_free(path);
282
283                 RemoveCheat(i);
284         }
285
286         LoadCheatListItems(i); // FIXME: should remove it from the list directly
287                                // rather than regenerating the whole list
288 }
289
290 static void OnCheatListDlg_EnableToggled(GtkWidget *widget, gchar *path, gpointer user_data) {
291         int i = atoi(path);
292
293         assert(i >= 0 && i < NumCheats);
294         Cheats[i].Enabled ^= 1;
295
296         LoadCheatListItems(i); // FIXME: should modify it in the list directly
297                                // rather than regenerating the whole list
298 }
299
300 static void OnCheatListDlg_OpenClicked(GtkWidget *widget, gpointer user_data) {
301         GtkWidget *chooser;
302         gchar *filename;
303
304         GtkFileFilter *filter;
305
306         chooser = gtk_file_chooser_dialog_new (_("Open Cheat File"),
307                 NULL, GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
308                 GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
309
310         filename = g_build_filename(getenv("HOME"), CHEATS_DIR, NULL);
311         gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (chooser), filename);
312         g_free(filename);
313
314         filter = gtk_file_filter_new ();
315         gtk_file_filter_add_pattern (filter, "*.cht");
316         gtk_file_filter_set_name (filter, _("PCSX Cheat Code Files (*.cht)"));
317         gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser), filter);
318
319         filter = gtk_file_filter_new ();
320         gtk_file_filter_add_pattern (filter, "*");
321         gtk_file_filter_set_name (filter, _("All Files"));
322         gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser), filter);
323
324         if (gtk_dialog_run (GTK_DIALOG (chooser)) == GTK_RESPONSE_OK) {
325                 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (chooser));
326                 gtk_widget_destroy (GTK_WIDGET (chooser));
327                 while (gtk_events_pending()) gtk_main_iteration();
328         } else {
329                 gtk_widget_destroy (GTK_WIDGET (chooser));
330                 while (gtk_events_pending()) gtk_main_iteration();
331                 return;
332         }
333
334         LoadCheats(filename);
335
336         g_free(filename);
337
338         LoadCheatListItems(-1);
339 }
340
341 static void OnCheatListDlg_SaveClicked(GtkWidget *widget, gpointer user_data) {
342         GtkWidget *chooser;
343         gchar *filename;
344         GtkFileFilter *filter;
345
346         chooser = gtk_file_chooser_dialog_new(_("Save Cheat File"),
347                 NULL, GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
348                 GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
349
350         filename = g_build_filename(getenv("HOME"), CHEATS_DIR, NULL);
351         gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(chooser), filename);
352         g_free(filename);
353
354         filter = gtk_file_filter_new();
355         gtk_file_filter_add_pattern(filter, "*.cht");
356         gtk_file_filter_set_name(filter, _("PCSX Cheat Code Files (*.cht)"));
357         gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(chooser), filter);
358
359         filter = gtk_file_filter_new();
360         gtk_file_filter_add_pattern(filter, "*");
361         gtk_file_filter_set_name(filter, _("All Files (*.*)"));
362         gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(chooser), filter);
363
364         if (gtk_dialog_run(GTK_DIALOG(chooser)) == GTK_RESPONSE_OK) {
365                 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (chooser));
366                 gtk_widget_destroy (GTK_WIDGET(chooser));
367                 while (gtk_events_pending()) gtk_main_iteration();
368         } else {
369                 gtk_widget_destroy (GTK_WIDGET(chooser));
370                 while (gtk_events_pending()) gtk_main_iteration();
371                 return;
372         }
373
374         SaveCheats(filename);
375
376         g_free(filename);
377 }
378
379 static void OnCheatListDlg_CloseClicked() {
380         gtk_widget_destroy(CheatListDlg);
381         CheatListDlg = NULL;
382 }
383
384 // run the cheat list dialog
385 void RunCheatListDialog() {
386         GladeXML *xml;
387         GtkWidget *widget;
388         GtkTreeSelection *treesel;
389         GtkTreeViewColumn *column;
390         GtkCellRenderer *renderer;
391
392         xml = glade_xml_new(PACKAGE_DATA_DIR "pcsx.glade2", "CheatListDlg", NULL);
393         if (!xml) {
394                 g_warning(_("Error: Glade interface could not be loaded!"));
395                 return;
396         }
397
398         CheatListDlg = glade_xml_get_widget(xml, "CheatListDlg");
399         gtk_window_set_title(GTK_WINDOW(CheatListDlg), _("Cheat Codes"));
400
401         widget = glade_xml_get_widget(xml, "GtkCList_Cheat");
402
403         // column for enable
404         renderer = gtk_cell_renderer_toggle_new();
405         column = gtk_tree_view_column_new_with_attributes(_("Enable"),
406                 renderer, "active", 0, NULL);
407         gtk_tree_view_append_column(GTK_TREE_VIEW(widget), column);
408
409         g_signal_connect(G_OBJECT(renderer), "toggled", G_CALLBACK(OnCheatListDlg_EnableToggled), 0);
410
411         // column for description
412         renderer = gtk_cell_renderer_text_new();
413         column = gtk_tree_view_column_new_with_attributes(_("Description"),
414                 renderer, "text", 1, NULL);
415         gtk_tree_view_append_column(GTK_TREE_VIEW(widget), column);
416
417         LoadCheatListItems(-1);
418
419         treesel = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
420         gtk_tree_selection_set_mode(treesel, GTK_SELECTION_SINGLE);
421         g_signal_connect_data(G_OBJECT (treesel), "changed",
422                                                   G_CALLBACK (CheatList_TreeSelectionChanged),
423                                                   NULL, NULL, G_CONNECT_AFTER);
424
425         widget = glade_xml_get_widget(xml, "addbutton1");
426         g_signal_connect_data(GTK_OBJECT(widget), "clicked",
427                         GTK_SIGNAL_FUNC(OnCheatListDlg_AddClicked), xml, NULL, G_CONNECT_AFTER);
428
429         widget = glade_xml_get_widget(xml, "editbutton1");
430         g_signal_connect_data(GTK_OBJECT(widget), "clicked",
431                         GTK_SIGNAL_FUNC(OnCheatListDlg_EditClicked), xml, NULL, G_CONNECT_AFTER);
432
433         widget = glade_xml_get_widget(xml, "delbutton1");
434         g_signal_connect_data(GTK_OBJECT(widget), "clicked",
435                         GTK_SIGNAL_FUNC(OnCheatListDlg_DelClicked), xml, NULL, G_CONNECT_AFTER);
436
437         widget = glade_xml_get_widget(xml, "loadbutton1");
438         g_signal_connect_data(GTK_OBJECT(widget), "clicked",
439                         GTK_SIGNAL_FUNC(OnCheatListDlg_OpenClicked), xml, NULL, G_CONNECT_AFTER);
440
441         widget = glade_xml_get_widget(xml, "savebutton1");
442         g_signal_connect_data(GTK_OBJECT(widget), "clicked",
443                         GTK_SIGNAL_FUNC(OnCheatListDlg_SaveClicked), xml, NULL, G_CONNECT_AFTER);
444
445         // Setup a handler for when Close or Cancel is clicked
446         g_signal_connect_data(GTK_OBJECT(CheatListDlg), "response",
447                         GTK_SIGNAL_FUNC(OnCheatListDlg_CloseClicked), xml, (GClosureNotify)g_object_unref, G_CONNECT_AFTER);
448
449         gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "savebutton1")), NumCheats);
450         gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "editbutton1")), FALSE);
451         gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "delbutton1")), FALSE);
452         gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "editbutton1")), FALSE);
453 }
454
455 ///////////////////////////////////////////////////////////////////////////////
456
457 #define SEARCH_EQUALVAL                         0
458 #define SEARCH_NOTEQUALVAL                      1
459 #define SEARCH_RANGE                            2
460 #define SEARCH_INCBY                            3
461 #define SEARCH_DECBY                            4
462 #define SEARCH_INC                                      5
463 #define SEARCH_DEC                                      6
464 #define SEARCH_DIFFERENT                        7
465 #define SEARCH_NOCHANGE                         8
466
467 #define SEARCHTYPE_8BIT                         0
468 #define SEARCHTYPE_16BIT                        1
469 #define SEARCHTYPE_32BIT                        2
470
471 #define SEARCHBASE_DEC                          0
472 #define SEARCHBASE_HEX                          1
473
474 static char current_search                      = SEARCH_EQUALVAL;
475 static char current_searchtype          = SEARCHTYPE_8BIT;
476 static char current_searchbase          = SEARCHBASE_DEC;
477 static uint32_t current_valuefrom       = 0;
478 static uint32_t current_valueto         = 0;
479
480 // update the cheat search dialog
481 static void UpdateCheatSearchDialog() {
482         GladeXML                *xml;
483         char                    buf[256];
484         int                             i;
485         u32                             addr;
486         GtkListStore    *store = gtk_list_store_new(1, G_TYPE_STRING);
487         GtkTreeIter             iter;
488         GtkWidget               *widget;
489
490         xml = glade_get_widget_tree(CheatSearchDlg);
491         widget = glade_xml_get_widget(xml, "GtkCList_Result");
492
493         gtk_combo_box_set_active(GTK_COMBO_BOX(glade_xml_get_widget(xml, "combo_searchfor")), current_search);
494         gtk_combo_box_set_active(GTK_COMBO_BOX(glade_xml_get_widget(xml, "combo_datatype")), current_searchtype);
495         gtk_combo_box_set_active(GTK_COMBO_BOX(glade_xml_get_widget(xml, "combo_database")), current_searchbase);
496
497         if (current_searchbase == SEARCHBASE_DEC) {
498                 sprintf(buf, "%u", current_valuefrom);
499                 gtk_entry_set_text(GTK_ENTRY(glade_xml_get_widget(xml, "entry_value")), buf);
500                 sprintf(buf, "%u", current_valueto);
501                 gtk_entry_set_text(GTK_ENTRY(glade_xml_get_widget(xml, "entry_valueto")), buf);
502         }
503         else {
504                 sprintf(buf, "%X", current_valuefrom);
505                 gtk_entry_set_text(GTK_ENTRY(glade_xml_get_widget(xml, "entry_value")), buf);
506                 sprintf(buf, "%X", current_valueto);
507                 gtk_entry_set_text(GTK_ENTRY(glade_xml_get_widget(xml, "entry_valueto")), buf);
508         }
509
510         if (current_search == SEARCH_RANGE) {
511                 gtk_widget_show(GTK_WIDGET(glade_xml_get_widget(xml, "label_valueto")));
512                 gtk_widget_show(GTK_WIDGET(glade_xml_get_widget(xml, "entry_valueto")));
513         }
514         else {
515                 gtk_widget_hide(GTK_WIDGET(glade_xml_get_widget(xml, "label_valueto")));
516                 gtk_widget_hide(GTK_WIDGET(glade_xml_get_widget(xml, "entry_valueto")));
517         }
518
519         if (current_search >= SEARCH_INC) {
520                 gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "entry_value")), FALSE);
521         }
522         else {
523                 gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "entry_value")), TRUE);
524         }
525
526         if (current_search >= SEARCH_INCBY && prevM == NULL) {
527                 gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btn_start")), FALSE);
528         }
529         else {
530                 gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btn_start")), TRUE);
531         }
532
533         gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btn_freeze")), FALSE);
534         gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btn_modify")), FALSE);
535         gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btn_copy")), FALSE);
536
537         if (prevM != NULL) {
538                 gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "combo_datatype")), FALSE);
539
540                 if (NumSearchResults > 100) {
541                         // too many results to be shown
542                         gtk_list_store_append(store, &iter);
543                         gtk_list_store_set(store, &iter, 0, _("Too many addresses found."), -1);
544                         gtk_widget_set_sensitive(widget, FALSE);
545                 }
546                 else {
547                         for (i = 0; i < NumSearchResults; i++) {
548                                 addr = SearchResults[i];
549
550                                 switch (current_searchtype) {
551                                         case SEARCHTYPE_8BIT:
552                                                 sprintf(buf, _("%.8X    Current: %u (%.2X), Previous: %u (%.2X)"),
553                                                         addr, PSXMu8(addr), PSXMu8(addr), PrevMu8(addr), PrevMu8(addr));
554                                                 break;
555
556                                         case SEARCHTYPE_16BIT:
557                                                 sprintf(buf, _("%.8X    Current: %u (%.4X), Previous: %u (%.4X)"),
558                                                         addr, PSXMu16(addr), PSXMu16(addr), PrevMu16(addr), PrevMu16(addr));
559                                                 break;
560
561                                         case SEARCHTYPE_32BIT:
562                                                 sprintf(buf, _("%.8X    Current: %u (%.8X), Previous: %u (%.8X)"),
563                                                         addr, PSXMu32(addr), PSXMu32(addr), PrevMu32(addr), PrevMu32(addr));
564                                                 break;
565
566                                         default:
567                                                 assert(FALSE); // impossible
568                                                 break;
569                                 }
570
571                                 gtk_list_store_append(store, &iter);
572                                 gtk_list_store_set(store, &iter, 0, buf, -1);
573                         }
574                         gtk_widget_set_sensitive(widget, TRUE);
575                 }
576
577                 sprintf(buf, _("Founded Addresses: %d"), NumSearchResults);
578                 gtk_label_set_text(GTK_LABEL(glade_xml_get_widget(xml, "label_resultsfound")), buf);
579         }
580         else {
581                 gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "combo_datatype")), TRUE);
582                 gtk_widget_set_sensitive(widget, FALSE);
583
584                 gtk_label_set_text(GTK_LABEL(glade_xml_get_widget(xml, "label_resultsfound")),
585                         _("Enter the values and start your search."));
586         }
587
588         gtk_tree_view_set_model(GTK_TREE_VIEW(widget), GTK_TREE_MODEL(store));
589         g_object_unref(G_OBJECT(store));
590         gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(widget), TRUE);
591         gtk_widget_show(widget);
592 }
593
594 // get the current selected result index in the list
595 static int GetSelectedResultIndex() {
596         GladeXML                        *xml;
597         GtkTreeSelection        *selection;
598         GtkTreeIter                     iter;
599         GtkTreeModel            *model;
600         GtkTreePath                     *path;
601         gboolean                        selected;
602         int                                     i;
603
604         xml = glade_get_widget_tree(CheatSearchDlg);
605
606         selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(glade_xml_get_widget(xml, "GtkCList_Result")));
607         selected = gtk_tree_selection_get_selected(selection, &model, &iter);
608
609         if (!selected) {
610                 return -1;
611         }
612
613         path = gtk_tree_model_get_path(model, &iter);
614         i = *gtk_tree_path_get_indices(path);
615         gtk_tree_path_free(path);
616
617         assert(i < NumSearchResults);
618         return i;
619 }
620
621 // add cheat code to freeze the value
622 static void OnCheatSearchDlg_FreezeClicked(GtkWidget *widget, gpointer user_data) {
623         GtkWidget          *dlg;
624         GtkWidget          *box, *hbox, *label, *descr_edit, *value_edit;
625         char                    buf[256];
626         u32                             addr, val = 0;
627
628         addr = SearchResults[GetSelectedResultIndex()];
629
630         dlg = gtk_dialog_new_with_buttons(_("Freeze value"), GTK_WINDOW(CheatListDlg),
631                 GTK_DIALOG_MODAL, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
632                 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, NULL);
633
634         box = GTK_WIDGET(GTK_DIALOG(dlg)->vbox);
635
636         label = gtk_label_new(_("Description:"));
637         gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 5);
638         gtk_widget_show(label);
639
640         descr_edit = gtk_entry_new();
641         gtk_box_pack_start(GTK_BOX(box), descr_edit, FALSE, FALSE, 10);
642         gtk_widget_show(descr_edit);
643
644         hbox = gtk_hbox_new(FALSE, 0);
645         gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 15);
646
647         label = gtk_label_new(_("Value:"));
648         gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
649         gtk_widget_show(label);
650
651         value_edit = gtk_entry_new();
652         gtk_box_pack_start(GTK_BOX(hbox), value_edit, FALSE, FALSE, 10);
653         gtk_widget_show(value_edit);
654
655         switch (current_searchtype) {
656                 case SEARCHTYPE_8BIT:
657                         val = PSXMu8(addr);
658                         break;
659
660                 case SEARCHTYPE_16BIT:
661                         val = PSXMu16(addr);
662                         break;
663
664                 case SEARCHTYPE_32BIT:
665                         val = PSXMu32(addr);
666                         break;
667
668                 default:
669                         assert(FALSE); // should not reach here
670                         break;
671         }
672
673         sprintf(buf, "%u", val);
674         gtk_entry_set_text(GTK_ENTRY(value_edit), buf);
675
676         sprintf(buf, "%.8X", addr);
677         gtk_entry_set_text(GTK_ENTRY(descr_edit), buf);
678
679         gtk_window_set_position(GTK_WINDOW(dlg), GTK_WIN_POS_CENTER);
680         gtk_widget_show_all(dlg);
681
682         if (gtk_dialog_run(GTK_DIALOG(dlg)) == GTK_RESPONSE_ACCEPT) {
683                 val = 0;
684                 sscanf(gtk_entry_get_text(GTK_ENTRY(value_edit)), "%u", &val);
685
686                 switch (current_searchtype) {
687                         case SEARCHTYPE_8BIT:
688                                 if (val > (u32)0xFF) {
689                                         val = 0xFF;
690                                 }
691                                 sprintf(buf, "%.8X %.4X", (addr & 0x1FFFFF) | (CHEAT_CONST8 << 24), val);
692                                 break;
693
694                         case SEARCHTYPE_16BIT:
695                                 if (val > (u32)0xFFFF) {
696                                         val = 0xFFFF;
697                                 }
698                                 sprintf(buf, "%.8X %.4X", (addr & 0x1FFFFF) | (CHEAT_CONST16 << 24), val);
699                                 break;
700
701                         case SEARCHTYPE_32BIT:
702                                 sprintf(buf, "%.8X %.4X\n%.8X %.4X",
703                                         (addr & 0x1FFFFF) | (CHEAT_CONST16 << 24), val & 0xFFFF,
704                                         ((addr + 2) & 0x1FFFFF) | (CHEAT_CONST16 << 24), ((val & 0xFFFF0000) >> 16) & 0xFFFF);
705                                 break;
706
707                         default:
708                                 assert(FALSE); // should not reach here
709                                 break;
710                 }
711
712                 if (AddCheat(gtk_entry_get_text(GTK_ENTRY(descr_edit)), buf) == 0) {
713                         Cheats[NumCheats - 1].Enabled = 1;
714                 }
715         }
716
717         gtk_widget_destroy(dlg);
718 }
719
720 // modify the value on the fly
721 static void OnCheatSearchDlg_ModifyClicked(GtkWidget *widget, gpointer user_data) {
722         GtkWidget          *dlg;
723         GtkWidget          *box, *hbox, *label, *value_edit;
724         char                    buf[256];
725         u32                             addr, val = 0;
726
727         addr = SearchResults[GetSelectedResultIndex()];
728
729         dlg = gtk_dialog_new_with_buttons(_("Modify value"), GTK_WINDOW(CheatListDlg),
730                 GTK_DIALOG_MODAL, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
731                 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, NULL);
732
733         box = GTK_WIDGET(GTK_DIALOG(dlg)->vbox);
734         hbox = gtk_hbox_new(FALSE, 0);
735         gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 5);
736
737         label = gtk_label_new(_("New value:"));
738         gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
739         gtk_widget_show(label);
740
741         value_edit = gtk_entry_new();
742         gtk_box_pack_start(GTK_BOX(hbox), value_edit, FALSE, FALSE, 10);
743         gtk_widget_show(value_edit);
744
745         switch (current_searchtype) {
746                 case SEARCHTYPE_8BIT:
747                         val = PSXMu8(addr);
748                         break;
749
750                 case SEARCHTYPE_16BIT:
751                         val = PSXMu16(addr);
752                         break;
753
754                 case SEARCHTYPE_32BIT:
755                         val = PSXMu32(addr);
756                         break;
757
758                 default:
759                         assert(FALSE); // should not reach here
760                         break;
761         }
762
763         sprintf(buf, "%u", val);
764         gtk_entry_set_text(GTK_ENTRY(value_edit), buf);
765
766         gtk_window_set_position(GTK_WINDOW(dlg), GTK_WIN_POS_CENTER);
767         gtk_widget_show_all(dlg);
768
769         if (gtk_dialog_run(GTK_DIALOG(dlg)) == GTK_RESPONSE_ACCEPT) {
770                 val = 0;
771                 sscanf(gtk_entry_get_text(GTK_ENTRY(value_edit)), "%u", &val);
772
773                 switch (current_searchtype) {
774                         case SEARCHTYPE_8BIT:
775                                 if (val > 0xFF) {
776                                         val = 0xFF;
777                                 }
778                                 psxMemWrite8(addr, (u8)val);
779                                 break;
780
781                         case SEARCHTYPE_16BIT:
782                                 if (val > 0xFFFF) {
783                                         val = 0xFFFF;
784                                 }
785                                 psxMemWrite16(addr, (u16)val);
786                                 break;
787
788                         case SEARCHTYPE_32BIT:
789                                 psxMemWrite32(addr, (u32)val);
790                                 break;
791
792                         default:
793                                 assert(FALSE); // should not reach here
794                                 break;
795                 }
796
797                 UpdateCheatSearchDialog();
798         }
799
800         gtk_widget_destroy(dlg);
801 }
802
803 // copy the selected address to clipboard
804 static void OnCheatSearchDlg_CopyClicked(GtkWidget *widget, gpointer user_data) {
805         int                     i;
806         char            buf[9];
807
808         i = GetSelectedResultIndex();
809         assert(i != -1);
810
811         sprintf(buf, "%8X", SearchResults[i]);
812         buf[8] = '\0';
813
814         gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), buf, 8);
815 }
816
817 // preform the search
818 static void OnCheatSearchDlg_SearchClicked(GtkWidget *widget, gpointer user_data) {
819         GladeXML                *xml;
820
821         xml = glade_get_widget_tree(CheatSearchDlg);
822
823         current_search = gtk_combo_box_get_active(GTK_COMBO_BOX(glade_xml_get_widget(xml, "combo_searchfor")));
824         current_searchtype = gtk_combo_box_get_active(GTK_COMBO_BOX(glade_xml_get_widget(xml, "combo_datatype")));
825         current_searchbase = gtk_combo_box_get_active(GTK_COMBO_BOX(glade_xml_get_widget(xml, "combo_database")));
826         current_valuefrom = 0;
827         current_valueto = 0;
828
829         if (current_searchbase == SEARCHBASE_DEC) {
830                 sscanf(gtk_entry_get_text(GTK_ENTRY(glade_xml_get_widget(xml, "entry_value"))), "%u", &current_valuefrom);
831                 sscanf(gtk_entry_get_text(GTK_ENTRY(glade_xml_get_widget(xml, "entry_valueto"))), "%u", &current_valueto);
832         }
833         else {
834                 sscanf(gtk_entry_get_text(GTK_ENTRY(glade_xml_get_widget(xml, "entry_value"))), "%x", &current_valuefrom);
835                 sscanf(gtk_entry_get_text(GTK_ENTRY(glade_xml_get_widget(xml, "entry_valueto"))), "%x", &current_valueto);
836         }
837
838         switch (current_searchtype) {
839                 case SEARCHTYPE_8BIT:
840                         if (current_valuefrom > (u32)0xFF) {
841                                 current_valuefrom = 0xFF;
842                         }
843                         if (current_valueto > (u32)0xFF) {
844                                 current_valueto = 0xFF;
845                         }
846                         break;
847
848                 case SEARCHTYPE_16BIT:
849                         if (current_valuefrom > (u32)0xFFFF) {
850                                 current_valuefrom = 0xFFFF;
851                         }
852                         if (current_valueto > (u32)0xFFFF) {
853                                 current_valueto = 0xFFFF;
854                         }
855                         break;
856         }
857
858         if (current_search == SEARCH_RANGE && current_valuefrom > current_valueto) {
859                 u32 t = current_valuefrom;
860                 current_valuefrom = current_valueto;
861                 current_valueto = t;
862         }
863
864         switch (current_search) {
865                 case SEARCH_EQUALVAL:
866                         switch (current_searchtype) {
867                                 case SEARCHTYPE_8BIT:
868                                         CheatSearchEqual8((u8)current_valuefrom);
869                                         break;
870
871                                 case SEARCHTYPE_16BIT:
872                                         CheatSearchEqual16((u16)current_valuefrom);
873                                         break;
874
875                                 case SEARCHTYPE_32BIT:
876                                         CheatSearchEqual32((u32)current_valuefrom);
877                                         break;
878                         }
879                         break;
880
881                 case SEARCH_NOTEQUALVAL:
882                         switch (current_searchtype) {
883                                 case SEARCHTYPE_8BIT:
884                                         CheatSearchNotEqual8((u8)current_valuefrom);
885                                         break;
886
887                                 case SEARCHTYPE_16BIT:
888                                         CheatSearchNotEqual16((u16)current_valuefrom);
889                                         break;
890
891                                 case SEARCHTYPE_32BIT:
892                                         CheatSearchNotEqual32((u32)current_valuefrom);
893                                         break;
894                         }
895                         break;
896
897                 case SEARCH_RANGE:
898                         switch (current_searchtype) {
899                                 case SEARCHTYPE_8BIT:
900                                         CheatSearchRange8((u8)current_valuefrom, (u8)current_valueto);
901                                         break;
902
903                                 case SEARCHTYPE_16BIT:
904                                         CheatSearchRange16((u16)current_valuefrom, (u16)current_valueto);
905                                         break;
906
907                                 case SEARCHTYPE_32BIT:
908                                         CheatSearchRange32((u32)current_valuefrom, (u32)current_valueto);
909                                         break;
910                         }
911                         break;
912
913                 case SEARCH_INCBY:
914                         switch (current_searchtype) {
915                                 case SEARCHTYPE_8BIT:
916                                         CheatSearchIncreasedBy8((u8)current_valuefrom);
917                                         break;
918
919                                 case SEARCHTYPE_16BIT:
920                                         CheatSearchIncreasedBy16((u16)current_valuefrom);
921                                         break;
922
923                                 case SEARCHTYPE_32BIT:
924                                         CheatSearchIncreasedBy32((u32)current_valuefrom);
925                                         break;
926                         }
927                         break;
928
929                 case SEARCH_DECBY:
930                         switch (current_searchtype) {
931                                 case SEARCHTYPE_8BIT:
932                                         CheatSearchDecreasedBy8((u8)current_valuefrom);
933                                         break;
934
935                                 case SEARCHTYPE_16BIT:
936                                         CheatSearchDecreasedBy16((u16)current_valuefrom);
937                                         break;
938
939                                 case SEARCHTYPE_32BIT:
940                                         CheatSearchDecreasedBy32((u32)current_valuefrom);
941                                         break;
942                         }
943                         break;
944
945                 case SEARCH_INC:
946                         switch (current_searchtype) {
947                                 case SEARCHTYPE_8BIT:
948                                         CheatSearchIncreased8();
949                                         break;
950
951                                 case SEARCHTYPE_16BIT:
952                                         CheatSearchIncreased16();
953                                         break;
954
955                                 case SEARCHTYPE_32BIT:
956                                         CheatSearchIncreased32();
957                                         break;
958                         }
959                         break;
960
961                 case SEARCH_DEC:
962                         switch (current_searchtype) {
963                                 case SEARCHTYPE_8BIT:
964                                         CheatSearchDecreased8();
965                                         break;
966
967                                 case SEARCHTYPE_16BIT:
968                                         CheatSearchDecreased16();
969                                         break;
970
971                                 case SEARCHTYPE_32BIT:
972                                         CheatSearchDecreased32();
973                                         break;
974                         }
975                         break;
976
977                 case SEARCH_DIFFERENT:
978                         switch (current_searchtype) {
979                                 case SEARCHTYPE_8BIT:
980                                         CheatSearchDifferent8();
981                                         break;
982
983                                 case SEARCHTYPE_16BIT:
984                                         CheatSearchDifferent16();
985                                         break;
986
987                                 case SEARCHTYPE_32BIT:
988                                         CheatSearchDifferent32();
989                                         break;
990                         }
991                         break;
992
993                 case SEARCH_NOCHANGE:
994                         switch (current_searchtype) {
995                                 case SEARCHTYPE_8BIT:
996                                         CheatSearchNoChange8();
997                                         break;
998
999                                 case SEARCHTYPE_16BIT:
1000                                         CheatSearchNoChange16();
1001                                         break;
1002
1003                                 case SEARCHTYPE_32BIT:
1004                                         CheatSearchNoChange32();
1005                                         break;
1006                         }
1007                         break;
1008
1009                 default:
1010                         assert(FALSE); // not possible
1011                         break;
1012         }
1013
1014         UpdateCheatSearchDialog();
1015 }
1016
1017 // restart the search
1018 static void OnCheatSearchDlg_RestartClicked(GtkWidget *widget, gpointer user_data) {
1019         FreeCheatSearchResults();
1020         FreeCheatSearchMem();
1021
1022         current_search = SEARCH_EQUALVAL;
1023         current_searchtype = SEARCHTYPE_8BIT;
1024         current_searchbase = SEARCHBASE_DEC;
1025         current_valuefrom = 0;
1026         current_valueto = 0;
1027
1028         UpdateCheatSearchDialog();
1029 }
1030
1031 // close the cheat search window
1032 static void OnCheatSearchDlg_CloseClicked(GtkWidget *widget, gpointer user_data) {
1033         gtk_widget_destroy(CheatSearchDlg);
1034         CheatSearchDlg = NULL;
1035 }
1036
1037 static void OnCheatSearchDlg_SearchForChanged(GtkWidget *widget, gpointer user_data) {
1038         GladeXML *xml;
1039
1040         xml = glade_get_widget_tree(CheatSearchDlg);
1041
1042         if (gtk_combo_box_get_active(GTK_COMBO_BOX(widget)) == SEARCH_RANGE) {
1043                 gtk_widget_show(GTK_WIDGET(glade_xml_get_widget(xml, "label_valueto")));
1044                 gtk_widget_show(GTK_WIDGET(glade_xml_get_widget(xml, "entry_valueto")));
1045         }
1046         else {
1047                 gtk_widget_hide(GTK_WIDGET(glade_xml_get_widget(xml, "label_valueto")));
1048                 gtk_widget_hide(GTK_WIDGET(glade_xml_get_widget(xml, "entry_valueto")));
1049         }
1050
1051         if (gtk_combo_box_get_active(GTK_COMBO_BOX(widget)) >= SEARCH_INC) {
1052                 gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "entry_value")), FALSE);
1053         }
1054         else {
1055                 gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "entry_value")), TRUE);
1056         }
1057
1058         if (gtk_combo_box_get_active(GTK_COMBO_BOX(widget)) >= SEARCH_INCBY && prevM == NULL) {
1059                 gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btn_start")), FALSE);
1060         }
1061         else {
1062                 gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btn_start")), TRUE);
1063         }
1064 }
1065
1066 static void OnCheatSearchDlg_DataBaseChanged(GtkWidget *widget, gpointer user_data) {
1067         u32                             val;
1068         char                    buf[256];
1069         GladeXML                *xml;
1070
1071         xml = glade_get_widget_tree(CheatSearchDlg);
1072
1073         if (gtk_combo_box_get_active(GTK_COMBO_BOX(widget)) == SEARCHBASE_DEC) {
1074                 val = 0;
1075                 sscanf(gtk_entry_get_text(GTK_ENTRY(glade_xml_get_widget(xml, "entry_value"))), "%x", &val);
1076                 sprintf(buf, "%u", val);
1077                 gtk_entry_set_text(GTK_ENTRY(glade_xml_get_widget(xml, "entry_value")), buf);
1078
1079                 val = 0;
1080                 sscanf(gtk_entry_get_text(GTK_ENTRY(glade_xml_get_widget(xml, "entry_valueto"))), "%x", &val);
1081                 sprintf(buf, "%u", val);
1082                 gtk_entry_set_text(GTK_ENTRY(glade_xml_get_widget(xml, "entry_valueto")), buf);
1083         }
1084         else {
1085                 val = 0;
1086                 sscanf(gtk_entry_get_text(GTK_ENTRY(glade_xml_get_widget(xml, "entry_value"))), "%u", &val);
1087                 sprintf(buf, "%X", val);
1088                 gtk_entry_set_text(GTK_ENTRY(glade_xml_get_widget(xml, "entry_value")), buf);
1089
1090                 val = 0;
1091                 sscanf(gtk_entry_get_text(GTK_ENTRY(glade_xml_get_widget(xml, "entry_valueto"))), "%u", &val);
1092                 sprintf(buf, "%X", val);
1093                 gtk_entry_set_text(GTK_ENTRY(glade_xml_get_widget(xml, "entry_valueto")), buf);
1094         }
1095 }
1096
1097 static void CheatSearch_TreeSelectionChanged(GtkTreeSelection *selection, gpointer user_data) {
1098         GladeXML                        *xml;
1099
1100         xml = glade_get_widget_tree(CheatSearchDlg);
1101
1102         if (GetSelectedResultIndex() != -1) {
1103                 // If a row was selected, we can now enable some of the disabled widgets
1104                 gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btn_freeze")), TRUE);
1105                 gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btn_modify")), TRUE);
1106                 gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btn_copy")), TRUE);
1107         } else {
1108                 gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btn_freeze")), FALSE);
1109                 gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btn_modify")), FALSE);
1110                 gtk_widget_set_sensitive(GTK_WIDGET(glade_xml_get_widget(xml, "btn_copy")), FALSE);
1111         }
1112 }
1113
1114 // run the cheat search dialog
1115 void RunCheatSearchDialog() {
1116         GladeXML *xml;
1117         GtkWidget *widget;
1118         GtkCellRenderer *renderer;
1119         GtkTreeSelection *treesel;
1120         GtkTreeViewColumn *column;
1121
1122         xml = glade_xml_new(PACKAGE_DATA_DIR "pcsx.glade2", "CheatSearchDlg", NULL);
1123         if (!xml) {
1124                 g_warning(_("Error: Glade interface could not be loaded!"));
1125                 return;
1126         }
1127
1128         CheatSearchDlg = glade_xml_get_widget(xml, "CheatSearchDlg");
1129         gtk_window_set_title(GTK_WINDOW(CheatSearchDlg), _("Cheat Search"));
1130
1131         widget = glade_xml_get_widget(xml, "GtkCList_Result");
1132
1133         renderer = gtk_cell_renderer_text_new ();
1134         column = gtk_tree_view_column_new_with_attributes(_("Search Results"),
1135                 renderer, "text", 0, NULL);
1136         gtk_tree_view_append_column(GTK_TREE_VIEW(widget), column);
1137
1138         treesel = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
1139         gtk_tree_selection_set_mode (treesel, GTK_SELECTION_SINGLE);
1140         g_signal_connect_data(G_OBJECT(treesel), "changed",
1141                                                   G_CALLBACK(CheatSearch_TreeSelectionChanged),
1142                                                   NULL, NULL, G_CONNECT_AFTER);
1143
1144         UpdateCheatSearchDialog();
1145
1146         widget = glade_xml_get_widget(xml, "btn_freeze");
1147         g_signal_connect_data(GTK_OBJECT(widget), "clicked",
1148                 GTK_SIGNAL_FUNC(OnCheatSearchDlg_FreezeClicked), xml, NULL, G_CONNECT_AFTER);
1149
1150         widget = glade_xml_get_widget(xml, "btn_modify");
1151         g_signal_connect_data(GTK_OBJECT(widget), "clicked",
1152                 GTK_SIGNAL_FUNC(OnCheatSearchDlg_ModifyClicked), xml, NULL, G_CONNECT_AFTER);
1153
1154         widget = glade_xml_get_widget(xml, "btn_copy");
1155         g_signal_connect_data(GTK_OBJECT(widget), "clicked",
1156                 GTK_SIGNAL_FUNC(OnCheatSearchDlg_CopyClicked), xml, NULL, G_CONNECT_AFTER);
1157
1158         widget = glade_xml_get_widget(xml, "btn_start");
1159         g_signal_connect_data(GTK_OBJECT(widget), "clicked",
1160                 GTK_SIGNAL_FUNC(OnCheatSearchDlg_SearchClicked), xml, NULL, G_CONNECT_AFTER);
1161
1162         widget = glade_xml_get_widget(xml, "btn_restart");
1163         g_signal_connect_data(GTK_OBJECT(widget), "clicked",
1164                 GTK_SIGNAL_FUNC(OnCheatSearchDlg_RestartClicked), xml, NULL, G_CONNECT_AFTER);
1165
1166         widget = glade_xml_get_widget(xml, "combo_searchfor");
1167         g_signal_connect_data(GTK_OBJECT(widget), "changed",
1168                 GTK_SIGNAL_FUNC(OnCheatSearchDlg_SearchForChanged), xml, NULL, G_CONNECT_AFTER);
1169
1170         widget = glade_xml_get_widget(xml, "combo_database");
1171         g_signal_connect_data(GTK_OBJECT(widget), "changed",
1172                 GTK_SIGNAL_FUNC(OnCheatSearchDlg_DataBaseChanged), xml, NULL, G_CONNECT_AFTER);
1173
1174         g_signal_connect_data(GTK_OBJECT(CheatSearchDlg), "response",
1175                 GTK_SIGNAL_FUNC(OnCheatSearchDlg_CloseClicked), xml, (GClosureNotify)g_object_unref, G_CONNECT_AFTER);
1176 }