diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000..99bf66a
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,54 @@
+{
+ // Use IntelliSense to learn about possible attributes.
+ // Hover to view descriptions of existing attributes.
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "Debug OpenSuperClone",
+ "type": "cppdbg",
+ "request": "launch",
+ "program": "${workspaceFolder}/Debug/bin/opensuperclone",
+ "MIMode": "gdb",
+ "miDebuggerPath": "/usr/bin/gdb",
+ "miDebuggerServerAddress": "localhost:2345",
+ "cwd": "${workspaceFolder}/Debug/bin",
+ "useExtendedRemote": true,
+ "setupCommands": [
+ {
+ "description": "Enable pretty-printing for gdb",
+ "text": "-enable-pretty-printing",
+ "ignoreFailures": true
+ },
+ {
+ "description": "Use local filesystem instead of transferring from remote target",
+ "text": "set sysroot /",
+ "ignoreFailures": true
+ }
+ ]
+ },
+ {
+ "name": "Debug OSCViewer",
+ "type": "cppdbg",
+ "request": "launch",
+ "program": "${workspaceFolder}/Debug/bin/oscviewer",
+ "MIMode": "gdb",
+ "miDebuggerPath": "/usr/bin/gdb",
+ "miDebuggerServerAddress": "localhost:2345",
+ "cwd": "${workspaceFolder}/Debug/bin",
+ "useExtendedRemote": true,
+ "setupCommands": [
+ {
+ "description": "Enable pretty-printing for gdb",
+ "text": "-enable-pretty-printing",
+ "ignoreFailures": true
+ },
+ {
+ "description": "Use local filesystem instead of transferring from remote target",
+ "text": "set sysroot /",
+ "ignoreFailures": true
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index 9c1e517..55f2120 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -25,6 +25,22 @@
"clear": true
}
},
+ {
+ // Run OpenSuperClone with GDBServer (as root)
+ "label": "🐞 Run OpenSuperClone with GDBServer",
+ "type": "shell",
+ "linux": {
+ "command": "[ -f ./Debug/bin/opensuperclone ] || ./build.sh debug && sudo gdbserver localhost:2345 ${workspaceFolder}/Debug/bin/opensuperclone"
+ }
+ },
+ {
+ // Run OSCViewer with GDBServer
+ "label": "🐞 Run OSCViewer with GDBServer",
+ "type": "shell",
+ "linux": {
+ "command": "[ -f ./Debug/bin/oscviewer ] || ./build.sh debug && gdbserver localhost:2345 ${workspaceFolder}/Debug/bin/opensuperclone"
+ }
+ },
{
// Build Release.
"label": "🔧 Build Release",
diff --git a/README.md b/README.md
index b805077..df15e4c 100644
--- a/README.md
+++ b/README.md
@@ -60,7 +60,8 @@ Note that the Wiki is currently a work-in-progress and incomplete.
#### OpenSuperClone 2.5.1 (Work-In-Progress)
* OSCDriver 2.6.8: add support up to kernel 6.18.0 (thanks to piernov)
-* Add ability to save and load recovery settings
+* Add ability to save and load recovery settings, and change default settings for program start
+* OSCViewer: performance improvements and improved UI
#### OpenSuperClone 2.5
diff --git a/src/opensuperclone/clone_gui.h b/src/opensuperclone/clone_gui.h
index be5e8d0..3461257 100644
--- a/src/opensuperclone/clone_gui.h
+++ b/src/opensuperclone/clone_gui.h
@@ -486,6 +486,9 @@ char *default_asclepius_config_filename = "asclepius.cfg";
int default_window_width = 1350;
int default_window_height = 670;
+int default_window_width = 1150;
+int default_window_height = 690;
+
void select_file_ccc(void);
void select_ddrescue_file_ccc(void);
diff --git a/src/oscviewer/CMakeLists.txt b/src/oscviewer/CMakeLists.txt
index 9e48825..2ef5f41 100644
--- a/src/oscviewer/CMakeLists.txt
+++ b/src/oscviewer/CMakeLists.txt
@@ -46,6 +46,9 @@ target_link_directories(oscviewer PRIVATE ${LIBCONFIG_LIBRARY_DIRS})
target_compile_options(oscviewer PRIVATE ${LIBCONFIG_CFLAGS_OTHER})
target_link_libraries(oscviewer ${LIBCONFIG_LIBRARIES})
+# Add libm dependency
+target_link_libraries(oscviewer m)
+
target_compile_options(oscviewer PRIVATE ${CC_OPTIONS})
# Install executable
diff --git a/src/oscviewer/oscviewer.c b/src/oscviewer/oscviewer.c
index 2a3da30..819e9b5 100644
--- a/src/oscviewer/oscviewer.c
+++ b/src/oscviewer/oscviewer.c
@@ -7,6 +7,234 @@
#include "oscviewer.h"
#include "oscviewer_glade.h"
+static const int main_grid_size_values[] = {4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216};
+static const int auto_update_interval_values[] = {0, 5000, 10000, 30000, 60000, 120000, 300000};
+static const int show_timing_values[] = {0, 1, 2, 3, 4, 5, 7, 10, 15, 20, 25, 30, 40, 50, 60};
+
+static int find_value_index(const int *values, int count, int value)
+{
+ for (int i = 0; i < count; i++)
+ {
+ if (values[i] == value)
+ {
+ return i;
+ }
+ }
+ return 0;
+}
+
+static void set_combo_active_from_value(GtkWidget *combo, const int *values, int count, int value)
+{
+ if (combo == NULL)
+ {
+ return;
+ }
+ int index = find_value_index(values, count, value);
+ gtk_combo_box_set_active(GTK_COMBO_BOX(combo), index);
+}
+
+static void sync_preference_widgets(void)
+{
+ if (updating_preferences)
+ {
+ return;
+ }
+
+ updating_preferences = TRUE;
+
+ if (showgoodcheck != NULL)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(showgoodcheck), show_good_data ? TRUE : FALSE);
+ }
+ if (showbadcheck != NULL)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(showbadcheck), show_bad_head ? TRUE : FALSE);
+ }
+ if (showdomaincheck != NULL)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(showdomaincheck), show_domain ? TRUE : FALSE);
+ }
+ if (followcurrentcheck != NULL)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(followcurrentcheck), follow_current_on_update ? TRUE : FALSE);
+ }
+
+ if (autoupdatebuttonoff != NULL)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(autoupdatebuttonoff), auto_update_interval == 0);
+ }
+ if (autoupdatebutton5s != NULL)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(autoupdatebutton5s), auto_update_interval == 5000);
+ }
+ if (autoupdatebutton10s != NULL)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(autoupdatebutton10s), auto_update_interval == 10000);
+ }
+ if (autoupdatebutton30s != NULL)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(autoupdatebutton30s), auto_update_interval == 30000);
+ }
+ if (autoupdatebutton1m != NULL)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(autoupdatebutton1m), auto_update_interval == 60000);
+ }
+ if (autoupdatebutton2m != NULL)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(autoupdatebutton2m), auto_update_interval == 120000);
+ }
+ if (autoupdatebutton5m != NULL)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(autoupdatebutton5m), auto_update_interval == 300000);
+ }
+
+ if (showtimingbuttonoff != NULL)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(showtimingbuttonoff), show_timing == 0);
+ }
+ if (showtimingbutton1 != NULL)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(showtimingbutton1), show_timing == 1);
+ }
+ if (showtimingbutton2 != NULL)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(showtimingbutton2), show_timing == 2);
+ }
+ if (showtimingbutton3 != NULL)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(showtimingbutton3), show_timing == 3);
+ }
+ if (showtimingbutton4 != NULL)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(showtimingbutton4), show_timing == 4);
+ }
+ if (showtimingbutton5 != NULL)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(showtimingbutton5), show_timing == 5);
+ }
+ if (showtimingbutton7 != NULL)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(showtimingbutton7), show_timing == 7);
+ }
+ if (showtimingbutton10 != NULL)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(showtimingbutton10), show_timing == 10);
+ }
+ if (showtimingbutton15 != NULL)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(showtimingbutton15), show_timing == 15);
+ }
+ if (showtimingbutton20 != NULL)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(showtimingbutton20), show_timing == 20);
+ }
+ if (showtimingbutton25 != NULL)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(showtimingbutton25), show_timing == 25);
+ }
+ if (showtimingbutton30 != NULL)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(showtimingbutton30), show_timing == 30);
+ }
+ if (showtimingbutton40 != NULL)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(showtimingbutton40), show_timing == 40);
+ }
+ if (showtimingbutton50 != NULL)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(showtimingbutton50), show_timing == 50);
+ }
+ if (showtimingbutton60 != NULL)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(showtimingbutton60), show_timing == 60);
+ }
+
+ set_combo_active_from_value(settings_main_grid_size_combo, main_grid_size_values, (int)(sizeof(main_grid_size_values) / sizeof(main_grid_size_values[0])), main_grid_size);
+ set_combo_active_from_value(settings_auto_update_combo, auto_update_interval_values, (int)(sizeof(auto_update_interval_values) / sizeof(auto_update_interval_values[0])), auto_update_interval);
+ set_combo_active_from_value(settings_show_timing_combo, show_timing_values, (int)(sizeof(show_timing_values) / sizeof(show_timing_values[0])), show_timing);
+
+ if (settings_show_good_data_check != NULL)
+ {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(settings_show_good_data_check), show_good_data ? TRUE : FALSE);
+ }
+ if (settings_show_bad_head_check != NULL)
+ {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(settings_show_bad_head_check), show_bad_head ? TRUE : FALSE);
+ }
+ if (settings_show_domain_check != NULL)
+ {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(settings_show_domain_check), show_domain ? TRUE : FALSE);
+ }
+ if (settings_follow_current_check != NULL)
+ {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(settings_follow_current_check), follow_current_on_update ? TRUE : FALSE);
+ }
+
+ updating_preferences = FALSE;
+}
+
+static void update_auto_update_label(void)
+{
+ if (auto_update_label == NULL)
+ {
+ return;
+ }
+
+ if (auto_update_interval == 0)
+ {
+ snprintf(tempmessage, TEMP_MESSAGE_SIZE, "%s: %s", _("Auto-Update"), _("Off"));
+ }
+ else if (auto_update_interval == 5000)
+ {
+ snprintf(tempmessage, TEMP_MESSAGE_SIZE, "%s: %s", _("Auto-Update"), _("5 seconds"));
+ }
+ else if (auto_update_interval == 10000)
+ {
+ snprintf(tempmessage, TEMP_MESSAGE_SIZE, "%s: %s", _("Auto-Update"), _("10 seconds"));
+ }
+ else if (auto_update_interval == 30000)
+ {
+ snprintf(tempmessage, TEMP_MESSAGE_SIZE, "%s: %s", _("Auto-Update"), _("30 seconds"));
+ }
+ else if (auto_update_interval == 60000)
+ {
+ snprintf(tempmessage, TEMP_MESSAGE_SIZE, "%s: %s", _("Auto-Update"), _("1 minute"));
+ }
+ else if (auto_update_interval == 120000)
+ {
+ snprintf(tempmessage, TEMP_MESSAGE_SIZE, "%s: %s", _("Auto-Update"), _("2 minutes"));
+ }
+ else if (auto_update_interval == 300000)
+ {
+ snprintf(tempmessage, TEMP_MESSAGE_SIZE, "%s: %s", _("Auto-Update"), _("5 minutes"));
+ }
+ else
+ {
+ snprintf(tempmessage, TEMP_MESSAGE_SIZE, "%s: %d ms", _("Auto-Update"), auto_update_interval);
+ }
+
+ gtk_label_set_text(GTK_LABEL(auto_update_label), tempmessage);
+}
+
+static void apply_auto_update_interval(int interval)
+{
+ auto_update_interval = interval;
+
+ if (autotimer_on)
+ {
+ g_source_remove(timeout_tag);
+ autotimer_on = 0;
+ }
+
+ if (auto_update_interval > 0)
+ {
+ timeout_tag = g_timeout_add(auto_update_interval, (GSourceFunc)reload_file, NULL);
+ autotimer_on = 1;
+ }
+
+ update_auto_update_label();
+}
+
int main(int argc, char **argv)
{
bindtextdomain("oscviewer", OSC_LANG_PATH);
@@ -132,6 +360,62 @@ int main(int argc, char **argv)
gtk_window_set_title(GTK_WINDOW(settings_window), _("Settings"));
g_signal_connect(settings_window, "delete-event", G_CALLBACK(gtk_widget_hide_on_delete), NULL);
+ settings_view_label = GTK_WIDGET(gtk_builder_get_object(builder, "settings_view_label"));
+ settings_main_grid_size_combo = GTK_WIDGET(gtk_builder_get_object(builder, "settings_main_grid_size_combo"));
+ settings_auto_update_combo = GTK_WIDGET(gtk_builder_get_object(builder, "settings_auto_update_combo"));
+ settings_show_good_data_check = GTK_WIDGET(gtk_builder_get_object(builder, "settings_show_good_data_check"));
+ settings_show_bad_head_check = GTK_WIDGET(gtk_builder_get_object(builder, "settings_show_bad_head_check"));
+ settings_show_domain_check = GTK_WIDGET(gtk_builder_get_object(builder, "settings_show_domain_check"));
+ settings_show_timing_combo = GTK_WIDGET(gtk_builder_get_object(builder, "settings_show_timing_combo"));
+ settings_follow_current_check = GTK_WIDGET(gtk_builder_get_object(builder, "settings_follow_current_check"));
+
+ if (settings_main_grid_size_combo != NULL)
+ {
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(settings_main_grid_size_combo), _("4K"));
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(settings_main_grid_size_combo), _("8K"));
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(settings_main_grid_size_combo), _("16K"));
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(settings_main_grid_size_combo), _("32K"));
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(settings_main_grid_size_combo), _("64K"));
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(settings_main_grid_size_combo), _("128K"));
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(settings_main_grid_size_combo), _("256K"));
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(settings_main_grid_size_combo), _("512K"));
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(settings_main_grid_size_combo), _("1M"));
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(settings_main_grid_size_combo), _("2M"));
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(settings_main_grid_size_combo), _("4M"));
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(settings_main_grid_size_combo), _("8M"));
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(settings_main_grid_size_combo), _("16M"));
+ }
+
+ if (settings_auto_update_combo != NULL)
+ {
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(settings_auto_update_combo), _("Off"));
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(settings_auto_update_combo), _("5 seconds"));
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(settings_auto_update_combo), _("10 seconds"));
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(settings_auto_update_combo), _("30 seconds"));
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(settings_auto_update_combo), _("1 minute"));
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(settings_auto_update_combo), _("2 minutes"));
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(settings_auto_update_combo), _("5 minutes"));
+ }
+
+ if (settings_show_timing_combo != NULL)
+ {
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(settings_show_timing_combo), _("Off"));
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(settings_show_timing_combo), _("1"));
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(settings_show_timing_combo), _("2"));
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(settings_show_timing_combo), _("3"));
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(settings_show_timing_combo), _("4"));
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(settings_show_timing_combo), _("5"));
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(settings_show_timing_combo), _("7"));
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(settings_show_timing_combo), _("10"));
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(settings_show_timing_combo), _("15"));
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(settings_show_timing_combo), _("20"));
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(settings_show_timing_combo), _("25"));
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(settings_show_timing_combo), _("30"));
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(settings_show_timing_combo), _("40"));
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(settings_show_timing_combo), _("50"));
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(settings_show_timing_combo), _("60"));
+ }
+
// set it to exit if closed
g_signal_connect(G_OBJECT(main_window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
@@ -159,8 +443,7 @@ int main(int argc, char **argv)
gtk_label_set_text(GTK_LABEL(domain_log_label), tempmessage);
auto_update_label = GTK_WIDGET(gtk_builder_get_object(builder, "auto_update_label"));
- snprintf(tempmessage, TEMP_MESSAGE_SIZE, "%s: %s", _("Auto-Update"), _("Off"));
- gtk_label_set_text(GTK_LABEL(auto_update_label), tempmessage);
+ update_auto_update_label();
block_information_label = GTK_WIDGET(gtk_builder_get_object(builder, "block_information_label"));
@@ -169,6 +452,7 @@ int main(int argc, char **argv)
gtk_menu_item_set_label(GTK_MENU_ITEM(optionsmi), _("View"));
// left res menu
+ jumpcurrentmi = GTK_WIDGET(gtk_builder_get_object(builder, "jumpcurrentmi"));
leftresolutionmi = GTK_WIDGET(gtk_builder_get_object(builder, "leftresolutionmi"));
leftresbutton1 = GTK_WIDGET(gtk_builder_get_object(builder, "leftresbutton1"));
leftresbutton2 = GTK_WIDGET(gtk_builder_get_object(builder, "leftresbutton2"));
@@ -383,11 +667,17 @@ int main(int argc, char **argv)
showdomaincheck = GTK_WIDGET(gtk_builder_get_object(builder, "showdomaincheck"));
gtk_menu_item_set_label(GTK_MENU_ITEM(showdomaincheck), _("Show Domain"));
+ followcurrentcheck = GTK_WIDGET(gtk_builder_get_object(builder, "followcurrentcheck"));
+ gtk_menu_item_set_label(GTK_MENU_ITEM(followcurrentcheck), _("Follow Current on Auto-Update"));
if (show_domain)
{
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(showdomaincheck), TRUE);
}
+ if (follow_current_on_update)
+ {
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(followcurrentcheck), TRUE);
+ }
// help menu
helpmi = GTK_WIDGET(gtk_builder_get_object(builder, "helpmi"));
@@ -450,6 +740,9 @@ int main(int argc, char **argv)
gtk_label_set_text(GTK_LABEL(block_color_label), _("Block Colors"));
gtk_label_set_text(GTK_LABEL(marker_color_label), _("Marker Colors"));
+ sync_preference_widgets();
+ apply_auto_update_interval(auto_update_interval);
+
// add keyboard shortcuts
GtkAccelGroup *accel_group = gtk_accel_group_new();
gtk_window_add_accel_group(GTK_WINDOW(main_window), accel_group);
@@ -460,6 +753,7 @@ int main(int argc, char **argv)
gtk_widget_add_accelerator(showgoodcheck, "activate", accel_group, GDK_KEY_g, GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE);
gtk_widget_add_accelerator(showbadcheck, "activate", accel_group, GDK_KEY_b, GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE);
gtk_widget_add_accelerator(showdomaincheck, "activate", accel_group, GDK_KEY_d, GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator(jumpcurrentmi, "activate", accel_group, GDK_KEY_j, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
// set it to exit if the quit item is selected
g_signal_connect(G_OBJECT(quitmi), "activate", G_CALLBACK(gtk_main_quit), NULL);
@@ -476,11 +770,21 @@ int main(int argc, char **argv)
// set it to open the settings window if the settings item is selected
g_signal_connect(G_OBJECT(settingsmi), "activate", G_CALLBACK(show_settings_window), NULL);
+ g_signal_connect(G_OBJECT(settings_main_grid_size_combo), "changed", G_CALLBACK(settings_main_grid_size_changed), NULL);
+ g_signal_connect(G_OBJECT(settings_auto_update_combo), "changed", G_CALLBACK(settings_auto_update_changed), NULL);
+ g_signal_connect(G_OBJECT(settings_show_good_data_check), "toggled", G_CALLBACK(settings_toggle_show_good), NULL);
+ g_signal_connect(G_OBJECT(settings_show_bad_head_check), "toggled", G_CALLBACK(settings_toggle_show_bad), NULL);
+ g_signal_connect(G_OBJECT(settings_show_domain_check), "toggled", G_CALLBACK(settings_toggle_show_domain), NULL);
+ g_signal_connect(G_OBJECT(settings_show_timing_combo), "changed", G_CALLBACK(settings_show_timing_changed), NULL);
+ g_signal_connect(G_OBJECT(settings_follow_current_check), "toggled", G_CALLBACK(settings_toggle_follow_current), NULL);
+
g_signal_connect(G_OBJECT(leftresbutton1), "activate", G_CALLBACK(change_left_resolution), GINT_TO_POINTER(1));
g_signal_connect(G_OBJECT(leftresbutton2), "activate", G_CALLBACK(change_left_resolution), GINT_TO_POINTER(2));
g_signal_connect(G_OBJECT(leftresbutton3), "activate", G_CALLBACK(change_left_resolution), GINT_TO_POINTER(3));
g_signal_connect(G_OBJECT(leftresbutton4), "activate", G_CALLBACK(change_left_resolution), GINT_TO_POINTER(4));
+ g_signal_connect(G_OBJECT(jumpcurrentmi), "activate", G_CALLBACK(jump_to_current), NULL);
+
g_signal_connect(G_OBJECT(mainresbutton4), "activate", G_CALLBACK(change_main_resolution), GINT_TO_POINTER(4));
g_signal_connect(G_OBJECT(mainresbutton6), "activate", G_CALLBACK(change_main_resolution), GINT_TO_POINTER(6));
g_signal_connect(G_OBJECT(mainresbutton8), "activate", G_CALLBACK(change_main_resolution), GINT_TO_POINTER(8));
@@ -516,6 +820,7 @@ int main(int argc, char **argv)
g_signal_connect(G_OBJECT(showbadcheck), "activate", G_CALLBACK(toggle_showbad), NULL);
g_signal_connect(G_OBJECT(showdomaincheck), "activate", G_CALLBACK(toggle_showdomain), NULL);
+ g_signal_connect(G_OBJECT(followcurrentcheck), "activate", G_CALLBACK(toggle_follow_current_menu), NULL);
g_signal_connect(G_OBJECT(showtimingbuttonoff), "activate", G_CALLBACK(set_show_timing), GINT_TO_POINTER(0));
g_signal_connect(G_OBJECT(showtimingbutton1), "activate", G_CALLBACK(set_show_timing), GINT_TO_POINTER(1));
@@ -617,6 +922,271 @@ int main(int argc, char **argv)
return 0;
}
+static void clear_render_cache(cairo_surface_t **surface, gint *width, gint *height)
+{
+ if (*surface != NULL)
+ {
+ cairo_surface_destroy(*surface);
+ *surface = NULL;
+ }
+ *width = 0;
+ *height = 0;
+}
+
+static void invalidate_render_caches(gboolean top_dirty, gboolean main_dirty, gboolean left_dirty)
+{
+ if (top_dirty)
+ {
+ top_render_cache_dirty = TRUE;
+ }
+ if (main_dirty)
+ {
+ main_render_cache_dirty = TRUE;
+ }
+ if (left_dirty)
+ {
+ left_render_cache_dirty = TRUE;
+ }
+}
+
+static void render_main_contents(cairo_t *cr, int clip_left, int clip_top, int clip_width, int clip_height, gdouble scroll_position)
+{
+ double total_squares = main_grid_size;
+ double pixels = total_squares * main_square_size * main_square_size;
+
+ double x, y, w, l, r, g, b;
+ int max_width = main_scrolled_window_width - 25;
+ if (max_width <= 0)
+ {
+ max_width = 1;
+ }
+ int adjusted_height = (pixels / max_width) + 1;
+ gtk_widget_set_size_request(GTK_WIDGET(main_drawing_area), max_width, adjusted_height + 1);
+
+ get_rgb_color(WHITE);
+ r = rcolor;
+ g = gcolor;
+ b = bcolor;
+ x = 0;
+ y = 0;
+ w = clip_width;
+ l = clip_height;
+ cairo_set_source_rgb(cr, r, g, b);
+ cairo_rectangle(cr, x, y, w, l);
+ cairo_fill(cr);
+
+ if (total_size > 0)
+ {
+ snprintf(tempmessage, TEMP_MESSAGE_SIZE, "redrawing main width = %d, height = %d\n", main_drawing_area_width, main_drawing_area_height);
+ message_debug(tempmessage, 0);
+ snprintf(tempmessage, TEMP_MESSAGE_SIZE, "scroll = %f\n", scroll_position);
+ message_debug(tempmessage, 0);
+
+ int scroll_row_start = scroll_position / main_square_size;
+ int scroll_row_end = ((scroll_position + clip_height) / main_square_size) + 1;
+ int columns = main_drawing_area_width / main_square_size;
+ int rows = main_drawing_area_height / main_square_size;
+ int squares = columns * rows;
+ if (columns <= 0 || rows <= 0 || squares <= 0)
+ {
+ return;
+ }
+
+ long long blocks_per_square = total_size / (squares - 1);
+ square_adjust = main_square_size / 32;
+ int adjustment = 1;
+ while (total_size > squares * blocks_per_square)
+ {
+ adjustment++;
+ blocks_per_square = total_size / (squares - adjustment);
+ }
+ snprintf(tempmessage, TEMP_MESSAGE_SIZE, "total_size=%lld, squares*blocks_per_square=%lld\n", total_size, squares * blocks_per_square);
+ message_debug(tempmessage, 0);
+
+ int row_start = scroll_row_start;
+ if (row_start < 0)
+ {
+ row_start = 0;
+ }
+ int row_end = scroll_row_end;
+ if (row_end >= rows)
+ {
+ row_end = rows - 1;
+ }
+
+ for (int i = row_start; i <= row_end; i++)
+ {
+ if (i < scroll_row_start || i > scroll_row_end)
+ {
+ continue;
+ }
+ for (int n = 0; n < columns; n++)
+ {
+ int count = (i * columns) + n;
+ if (count >= squares)
+ {
+ break;
+ }
+
+ int color = 0;
+ int bad_head = 0;
+ int good_data = 0;
+ long long position = count * blocks_per_square;
+ int status_bits = get_block_status(position, blocks_per_square);
+ int time_bits = get_block_timing(position, blocks_per_square);
+ int in_domain = process_domain(position, blocks_per_square, FINISHED, FINISHED);
+ if (status_bits & NONTRIMMED_BIT)
+ {
+ color = nontrimmed_color;
+ }
+ else if (status_bits & NONDIVIDED_BIT)
+ {
+ color = nondivided_color;
+ }
+ else if (status_bits & NONSCRAPED_BIT)
+ {
+ color = nonscraped_color;
+ }
+ else if (status_bits & BAD_BIT)
+ {
+ color = bad_color;
+ }
+ else if (status_bits & NONTRIED_BIT)
+ {
+ color = nontried_color;
+ }
+ else if (status_bits & FINISHED_BIT)
+ {
+ color = good_color;
+ }
+ else if (status_bits & UNKNOWN_BIT)
+ {
+ color = unknown_color;
+ }
+ if (status_bits & BAD_HEAD_BIT)
+ {
+ bad_head = 1;
+ }
+ if (status_bits & FINISHED_BIT)
+ {
+ good_data = 1;
+ }
+ get_rgb_color(color);
+ r = rcolor;
+ g = gcolor;
+ b = bcolor;
+ cairo_set_source_rgb(cr, r, g, b);
+ cairo_rectangle(cr, (n * main_square_size) + 1 + square_adjust - clip_left, (i * main_square_size) + 1 + square_adjust - clip_top, main_square_size - 1 - (square_adjust * 2), main_square_size - 1 - (square_adjust * 2));
+ cairo_fill(cr);
+
+ if (bad_head && show_bad_head)
+ {
+ int spot_size = main_square_size - 3;
+ int spot_adjust = 2;
+ get_rgb_color(bad_head_color);
+ r = rcolor;
+ g = gcolor;
+ b = bcolor;
+ cairo_set_source_rgb(cr, r, g, b);
+ cairo_rectangle(cr, (n * main_square_size) + spot_adjust - clip_left, (i * main_square_size) + spot_adjust - clip_top, spot_size, spot_size);
+ cairo_stroke(cr);
+ }
+
+ if (good_data && show_good_data)
+ {
+ int spot_size = main_square_size - 3;
+ int spot_adjust = 2;
+ get_rgb_color(good_color);
+ r = rcolor;
+ g = gcolor;
+ b = bcolor;
+ cairo_set_source_rgb(cr, r, g, b);
+ cairo_rectangle(cr, (n * main_square_size) + spot_adjust - clip_left, (i * main_square_size) + spot_adjust - clip_top, spot_size, spot_size);
+ cairo_stroke(cr);
+ }
+
+ if ((time_bits >= show_timing) && show_timing)
+ {
+ int spot_size = main_square_size - 3;
+ int spot_adjust = 2;
+ get_rgb_color(time_color);
+ r = rcolor;
+ g = gcolor;
+ b = bcolor;
+ cairo_set_source_rgb(cr, r, g, b);
+ cairo_rectangle(cr, (n * main_square_size) + spot_adjust - clip_left, (i * main_square_size) + spot_adjust - clip_top, spot_size, spot_size);
+ cairo_stroke(cr);
+ }
+
+ if ((in_domain) && show_domain)
+ {
+ int spot_size = main_square_size - 3;
+ int spot_adjust = 2;
+ get_rgb_color(domain_color);
+ r = rcolor;
+ g = gcolor;
+ b = bcolor;
+ cairo_set_source_rgb(cr, r, g, b);
+ cairo_rectangle(cr, (n * main_square_size) + spot_adjust - clip_left, (i * main_square_size) + spot_adjust - clip_top, spot_size, spot_size);
+ cairo_stroke(cr);
+ }
+ }
+ }
+
+ long long position = current_position / blocks_per_square;
+ int current_row = position / columns;
+ int current_col = position % columns;
+ if (current_row >= row_start && current_row <= row_end)
+ {
+ int spot_size = main_square_size - 3;
+ int spot_adjust = 2;
+ get_rgb_color(current_color);
+ r = rcolor;
+ g = gcolor;
+ b = bcolor;
+ cairo_set_source_rgb(cr, r, g, b);
+ cairo_rectangle(cr, (current_col * main_square_size) + spot_adjust - clip_left, (current_row * main_square_size) + spot_adjust - clip_top, spot_size, spot_size);
+ cairo_stroke(cr);
+ }
+
+ for (int i = row_start; i <= row_end; i++)
+ {
+ if (i < scroll_row_start || i > scroll_row_end)
+ {
+ continue;
+ }
+ for (int n = 0; n < columns; n++)
+ {
+ int count = (i * columns) + n;
+ if (count >= squares)
+ {
+ break;
+ }
+
+ int xl = (n * main_square_size) + square_adjust;
+ int yl = (i * main_square_size) + square_adjust;
+ int xh = xl + main_square_size - (square_adjust * 2);
+ int yh = yl + main_square_size - (square_adjust * 2);
+ if (mouse_x != mouse_x_old && mouse_y != mouse_y_old && mouse_x >= xl && mouse_x <= xh && mouse_y >= yl && mouse_y <= yh)
+ {
+ int spot_size = main_square_size - 3;
+ int spot_adjust = 2;
+ get_rgb_color(selected_color);
+ r = rcolor;
+ g = gcolor;
+ b = bcolor;
+ cairo_set_source_rgb(cr, r, g, b);
+ cairo_rectangle(cr, (n * main_square_size) + spot_adjust - clip_left, (i * main_square_size) + spot_adjust - clip_top, spot_size, spot_size);
+ cairo_stroke(cr);
+ get_block_information(blocks_per_square * count, blocks_per_square);
+ mouse_x_old = mouse_x;
+ mouse_y_old = mouse_y;
+ }
+ }
+ }
+ }
+}
+
static gboolean on_button_press(GtkWidget *widget, GdkEventButton *event, GdkWindowEdge edge)
{
if (event->type == GDK_BUTTON_PRESS)
@@ -627,6 +1197,7 @@ static gboolean on_button_press(GtkWidget *widget, GdkEventButton *event, GdkWin
mouse_y = event->y;
snprintf(tempmessage, TEMP_MESSAGE_SIZE, "x=%d y=%d\n", mouse_x, mouse_y);
message_debug(tempmessage, 0);
+ invalidate_render_caches(FALSE, TRUE, TRUE);
gtk_widget_queue_draw(main_window);
}
}
@@ -849,231 +1420,48 @@ static gboolean top_drawing_expose_event(GtkWidget *self, cairo_t *cr, gpointer
static gboolean main_drawing_expose_event(GtkWidget *self, cairo_t *cr, gpointer user_data)
{
+ double clip_x1 = 0;
+ double clip_y1 = 0;
+ double clip_x2 = 0;
+ double clip_y2 = 0;
+ cairo_clip_extents(cr, &clip_x1, &clip_y1, &clip_x2, &clip_y2);
+
+ int clip_left = floor(clip_x1);
+ int clip_top = floor(clip_y1);
+ int clip_width = ceil(clip_x2) - clip_left;
+ int clip_height = ceil(clip_y2) - clip_top;
+
+ if (clip_width <= 0 || clip_height <= 0)
+ {
+ return 0;
+ }
+
double total_squares = main_grid_size;
double pixels = total_squares * main_square_size * main_square_size;
-
- double x, y, w, l, r, g, b;
int max_width = main_scrolled_window_width - 25;
int adjusted_height = (pixels / max_width) + 1;
gtk_widget_set_size_request(GTK_WIDGET(main_drawing_area), max_width, adjusted_height + 1);
- // printf("redrawing main width = %d, height = %d\n", main_drawing_area_width, main_drawing_area_height);
+ gdouble scroll_position = gtk_adjustment_get_value(GTK_ADJUSTMENT(gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(main_scrolled_window))));
+ gint scroll_key = (gint)scroll_position;
- get_rgb_color(WHITE);
- r = rcolor;
- g = gcolor;
- b = bcolor;
- x = 0;
- y = 0;
- w = main_drawing_area_width;
- l = main_drawing_area_height;
- cairo_set_source_rgb(cr, r, g, b);
- cairo_rectangle(cr, x, y, w, l);
- cairo_fill(cr);
-
- if (total_size > 0)
+ if (main_render_cache == NULL || main_render_cache_dirty || main_render_cache_width != clip_width || main_render_cache_height != clip_height || main_render_cache_scroll_position != scroll_key || main_render_cache_clip_x != clip_left || main_render_cache_clip_y != clip_top)
{
- snprintf(tempmessage, TEMP_MESSAGE_SIZE, "redrawing main width = %d, height = %d\n", main_drawing_area_width, main_drawing_area_height);
- message_debug(tempmessage, 0);
- gdouble scroll_position = gtk_adjustment_get_value(GTK_ADJUSTMENT(gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(main_scrolled_window))));
- snprintf(tempmessage, TEMP_MESSAGE_SIZE, "scroll = %f\n", scroll_position);
- message_debug(tempmessage, 0);
- int scroll_row_start = scroll_position / main_square_size;
- int scroll_row_end = scroll_row_start + (main_drawing_vbox_height / main_square_size);
- int columns = main_drawing_area_width / main_square_size;
- int rows = main_drawing_area_height / main_square_size;
- int squares = columns * rows;
- long long blocks_per_square = total_size / (squares - 1);
- square_adjust = main_square_size / 32;
- int adjustment = 1;
- while (total_size > squares * blocks_per_square)
- {
- adjustment++;
- blocks_per_square = total_size / (squares - adjustment);
- }
- snprintf(tempmessage, TEMP_MESSAGE_SIZE, "total_size=%lld, squares*blocks_per_square=%lld\n", total_size, squares * blocks_per_square);
- message_debug(tempmessage, 0);
-
- int count = 0;
- int i = 0;
- int n = 0;
-
- while (count < squares)
- {
- if (i >= scroll_row_start && i <= scroll_row_end)
- {
- int color = 0;
- int bad_head = 0;
- int good_data = 0;
- long long position = count * blocks_per_square;
- int status_bits = get_block_status(position, blocks_per_square);
- int time_bits = get_block_timing(position, blocks_per_square);
- int in_domain = process_domain(position, blocks_per_square, FINISHED, FINISHED);
- if (status_bits & NONTRIMMED_BIT)
- {
- color = nontrimmed_color;
- }
- else if (status_bits & NONDIVIDED_BIT)
- {
- color = nondivided_color;
- }
- else if (status_bits & NONSCRAPED_BIT)
- {
- color = nonscraped_color;
- }
- else if (status_bits & BAD_BIT)
- {
- color = bad_color;
- }
- else if (status_bits & NONTRIED_BIT)
- {
- color = nontried_color;
- }
- else if (status_bits & FINISHED_BIT)
- {
- color = good_color;
- }
- else if (status_bits & UNKNOWN_BIT)
- {
- color = unknown_color;
- }
- if (status_bits & BAD_HEAD_BIT)
- {
- bad_head = 1;
- }
- if (status_bits & FINISHED_BIT)
- {
- good_data = 1;
- }
- get_rgb_color(color);
- r = rcolor;
- g = gcolor;
- b = bcolor;
- cairo_set_source_rgb(cr, r, g, b);
- cairo_rectangle(cr, (n * main_square_size) + 1 + square_adjust, (i * main_square_size) + 1 + square_adjust, main_square_size - 1 - (square_adjust * 2), main_square_size - 1 - (square_adjust * 2));
- cairo_fill(cr);
-
- if (bad_head && show_bad_head)
- {
- int spot_size = main_square_size - 3;
- int spot_adjust = 2;
- get_rgb_color(bad_head_color);
- r = rcolor;
- g = gcolor;
- b = bcolor;
- cairo_set_source_rgb(cr, r, g, b);
- cairo_rectangle(cr, (n * main_square_size) + spot_adjust, (i * main_square_size) + spot_adjust, spot_size, spot_size);
- cairo_stroke(cr);
- }
-
- if (good_data && show_good_data)
- {
- int spot_size = main_square_size - 3;
- int spot_adjust = 2;
- get_rgb_color(good_color);
- r = rcolor;
- g = gcolor;
- b = bcolor;
- cairo_set_source_rgb(cr, r, g, b);
- cairo_rectangle(cr, (n * main_square_size) + spot_adjust, (i * main_square_size) + spot_adjust, spot_size, spot_size);
- cairo_stroke(cr);
- }
-
- if ((time_bits >= show_timing) && show_timing)
- {
- int spot_size = main_square_size - 3;
- int spot_adjust = 2;
- get_rgb_color(time_color);
- r = rcolor;
- g = gcolor;
- b = bcolor;
- cairo_set_source_rgb(cr, r, g, b);
- cairo_rectangle(cr, (n * main_square_size) + spot_adjust, (i * main_square_size) + spot_adjust, spot_size, spot_size);
- cairo_stroke(cr);
- }
-
- if ((in_domain) && show_domain)
- {
- int spot_size = main_square_size - 3;
- int spot_adjust = 2;
- get_rgb_color(domain_color);
- r = rcolor;
- g = gcolor;
- b = bcolor;
- cairo_set_source_rgb(cr, r, g, b);
- cairo_rectangle(cr, (n * main_square_size) + spot_adjust, (i * main_square_size) + spot_adjust, spot_size, spot_size);
- cairo_stroke(cr);
- }
- }
- count++;
- if (count > squares)
- {
- snprintf(tempmessage, TEMP_MESSAGE_SIZE, "main count out of range\n");
- message_debug(tempmessage, 0);
- break;
- }
- n++;
- if (n >= columns)
- {
- n = 0;
- i++;
- if (i >= rows)
- {
- snprintf(tempmessage, TEMP_MESSAGE_SIZE, "main rows out of range\n");
- message_debug(tempmessage, 0);
- break;
- }
- }
- }
-
- long long position = current_position / blocks_per_square;
- count = 0;
- for (i = 0; i < rows; i++)
- {
- for (n = 0; n < columns; n++)
- {
- if (position == count)
- {
- int spot_size = main_square_size - 3;
- int spot_adjust = 2;
- get_rgb_color(current_color);
- r = rcolor;
- g = gcolor;
- b = bcolor;
- cairo_set_source_rgb(cr, r, g, b);
- cairo_rectangle(cr, (n * main_square_size) + spot_adjust, (i * main_square_size) + spot_adjust, spot_size, spot_size);
- cairo_stroke(cr);
- }
-
- // int xl = (n * main_square_size) + 1 + square_adjust;
- // int yl = (i * main_square_size) + 1 + square_adjust;
- // int xh = xl + main_square_size - 1 - (square_adjust * 2);
- // int yh = yl + main_square_size - 1 - (square_adjust * 2);
- int xl = (n * main_square_size) + square_adjust;
- int yl = (i * main_square_size) + square_adjust;
- int xh = xl + main_square_size - (square_adjust * 2);
- int yh = yl + main_square_size - (square_adjust * 2);
- if (mouse_x != mouse_x_old && mouse_y != mouse_y_old && mouse_x >= xl && mouse_x <= xh && mouse_y >= yl && mouse_y <= yh)
- {
- int spot_size = main_square_size - 3;
- int spot_adjust = 2;
- get_rgb_color(selected_color);
- r = rcolor;
- g = gcolor;
- b = bcolor;
- cairo_set_source_rgb(cr, r, g, b);
- cairo_rectangle(cr, (n * main_square_size) + spot_adjust, (i * main_square_size) + spot_adjust, spot_size, spot_size);
- cairo_stroke(cr);
- get_block_information(blocks_per_square * count, blocks_per_square);
- mouse_x_old = mouse_x;
- mouse_y_old = mouse_y;
- }
-
- count++;
- }
- }
+ clear_render_cache(&main_render_cache, &main_render_cache_width, &main_render_cache_height);
+ main_render_cache = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, clip_width, clip_height);
+ cairo_t *cache_cr = cairo_create(main_render_cache);
+ render_main_contents(cache_cr, clip_left, clip_top, clip_width, clip_height, scroll_position);
+ cairo_destroy(cache_cr);
+ main_render_cache_dirty = FALSE;
+ main_render_cache_width = clip_width;
+ main_render_cache_height = clip_height;
+ main_render_cache_scroll_position = scroll_key;
+ main_render_cache_clip_x = clip_left;
+ main_render_cache_clip_y = clip_top;
}
+ cairo_set_source_surface(cr, main_render_cache, clip_left, clip_top);
+ cairo_paint(cr);
return 0;
}
@@ -1274,6 +1662,7 @@ void select_file(void)
}
}
+ invalidate_render_caches(FALSE, TRUE, TRUE);
gtk_widget_queue_draw(main_window);
}
gtk_widget_destroy(dialog);
@@ -1319,6 +1708,7 @@ void select_domain(void)
// }
// }
+ invalidate_render_caches(FALSE, TRUE, TRUE);
gtk_widget_queue_draw(main_window);
}
gtk_widget_destroy(dialog);
@@ -1355,6 +1745,7 @@ void select_dmde_domain(void)
gtk_label_set_text(GTK_LABEL(domain_log_label), tempmessage);
}
+ invalidate_render_caches(FALSE, TRUE, TRUE);
gtk_widget_queue_draw(main_window);
}
gtk_widget_destroy(dialog);
@@ -1391,6 +1782,12 @@ gint reload_file(void)
}
}
+ if (follow_current_on_update && auto_update_interval > 0)
+ {
+ jump_to_current(NULL, NULL);
+ }
+
+ invalidate_render_caches(FALSE, TRUE, TRUE);
gtk_widget_queue_draw(main_window);
return 1;
@@ -1398,51 +1795,28 @@ gint reload_file(void)
void set_autoupdate_timer(GtkWidget *w, gpointer data)
{
+ if (updating_preferences)
+ {
+ return;
+ }
+
if (autotimer_on)
{
g_source_remove(timeout_tag);
autotimer_on = 0;
}
- int time = GPOINTER_TO_INT(data);
- if (time > 0)
- {
- timeout_tag = g_timeout_add(time, (GSourceFunc)reload_file, NULL);
- autotimer_on = 1;
- }
-
- if (!autotimer_on)
- {
- snprintf(tempmessage, TEMP_MESSAGE_SIZE, "%s: %s", _("Auto-Update"), _("Off"));
- }
- else if (time == 5000)
- {
- snprintf(tempmessage, TEMP_MESSAGE_SIZE, "%s: %s", _("Auto-Update"), _("5 seconds"));
- }
- else if (time == 10000)
- {
- snprintf(tempmessage, TEMP_MESSAGE_SIZE, "%s: %s", _("Auto-Update"), _("10 seconds"));
- }
- else if (time == 30000)
- {
- snprintf(tempmessage, TEMP_MESSAGE_SIZE, "%s: %s", _("Auto-Update"), _("30 seconds"));
- }
- else if (time == 60000)
- {
- snprintf(tempmessage, TEMP_MESSAGE_SIZE, "%s: %s", _("Auto-Update"), _("1 minute"));
- }
- else if (time == 120000)
- {
- snprintf(tempmessage, TEMP_MESSAGE_SIZE, "%s: %s", _("Auto-Update"), _("2 minutes"));
- }
- else if (time == 300000)
- {
- snprintf(tempmessage, TEMP_MESSAGE_SIZE, "%s: %s", _("Auto-Update"), _("5 minutes"));
- }
- gtk_label_set_text(GTK_LABEL(auto_update_label), tempmessage);
+ apply_auto_update_interval(GPOINTER_TO_INT(data));
+ write_config_file();
+ sync_preference_widgets();
}
void toggle_showbad(GtkWidget *w, gpointer data)
{
+ if (updating_preferences)
+ {
+ return;
+ }
+
if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)))
{
show_bad_head = 1;
@@ -1452,11 +1826,19 @@ void toggle_showbad(GtkWidget *w, gpointer data)
show_bad_head = 0;
}
+ write_config_file();
+ sync_preference_widgets();
+ invalidate_render_caches(TRUE, TRUE, TRUE);
gtk_widget_queue_draw(main_window);
}
void toggle_showgood(GtkWidget *w, gpointer data)
{
+ if (updating_preferences)
+ {
+ return;
+ }
+
if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)))
{
show_good_data = 1;
@@ -1466,18 +1848,34 @@ void toggle_showgood(GtkWidget *w, gpointer data)
show_good_data = 0;
}
+ write_config_file();
+ sync_preference_widgets();
+ invalidate_render_caches(TRUE, TRUE, TRUE);
gtk_widget_queue_draw(main_window);
}
void set_show_timing(GtkWidget *w, gpointer data)
{
+ if (updating_preferences)
+ {
+ return;
+ }
+
show_timing = GPOINTER_TO_INT(data);
+ write_config_file();
+ sync_preference_widgets();
+ invalidate_render_caches(TRUE, TRUE, TRUE);
gtk_widget_queue_draw(main_window);
}
void toggle_showdomain(GtkWidget *w, gpointer data)
{
+ if (updating_preferences)
+ {
+ return;
+ }
+
if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)))
{
show_domain = 1;
@@ -1487,14 +1885,30 @@ void toggle_showdomain(GtkWidget *w, gpointer data)
show_domain = 0;
}
+ write_config_file();
+ sync_preference_widgets();
+ invalidate_render_caches(TRUE, TRUE, TRUE);
gtk_widget_queue_draw(main_window);
}
+void toggle_follow_current_menu(GtkWidget *w, gpointer data)
+{
+ if (updating_preferences)
+ {
+ return;
+ }
+
+ follow_current_on_update = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)) ? 1 : 0;
+ write_config_file();
+ sync_preference_widgets();
+}
+
void change_left_resolution(GtkWidget *w, gpointer data)
{
g_print("%d\n", GPOINTER_TO_INT(data));
left_square_size = GPOINTER_TO_INT(data);
+ invalidate_render_caches(TRUE, TRUE, TRUE);
gtk_widget_queue_draw(main_window);
}
@@ -1504,15 +1918,194 @@ void change_main_resolution(GtkWidget *w, gpointer data)
message_debug(tempmessage, 0);
main_square_size = GPOINTER_TO_INT(data);
+ invalidate_render_caches(TRUE, TRUE, TRUE);
gtk_widget_queue_draw(main_window);
}
void change_main_grid_size(GtkWidget *w, gpointer data)
{
+ if (updating_preferences)
+ {
+ return;
+ }
+
snprintf(tempmessage, TEMP_MESSAGE_SIZE, "%d\n", GPOINTER_TO_INT(data));
message_debug(tempmessage, 0);
main_grid_size = GPOINTER_TO_INT(data);
+ write_config_file();
+ sync_preference_widgets();
+ invalidate_render_caches(TRUE, TRUE, TRUE);
+ gtk_widget_queue_draw(main_window);
+}
+
+void settings_main_grid_size_changed(GtkWidget *w, gpointer data)
+{
+ if (updating_preferences)
+ {
+ return;
+ }
+
+ int index = gtk_combo_box_get_active(GTK_COMBO_BOX(w));
+ if (index < 0 || index >= (int)(sizeof(main_grid_size_values) / sizeof(main_grid_size_values[0])))
+ {
+ return;
+ }
+
+ main_grid_size = main_grid_size_values[index];
+ write_config_file();
+ sync_preference_widgets();
+ invalidate_render_caches(TRUE, TRUE, TRUE);
+ gtk_widget_queue_draw(main_window);
+}
+
+void settings_auto_update_changed(GtkWidget *w, gpointer data)
+{
+ if (updating_preferences)
+ {
+ return;
+ }
+
+ int index = gtk_combo_box_get_active(GTK_COMBO_BOX(w));
+ if (index < 0 || index >= (int)(sizeof(auto_update_interval_values) / sizeof(auto_update_interval_values[0])))
+ {
+ return;
+ }
+
+ apply_auto_update_interval(auto_update_interval_values[index]);
+ write_config_file();
+ sync_preference_widgets();
+}
+
+void settings_show_timing_changed(GtkWidget *w, gpointer data)
+{
+ if (updating_preferences)
+ {
+ return;
+ }
+
+ int index = gtk_combo_box_get_active(GTK_COMBO_BOX(w));
+ if (index < 0 || index >= (int)(sizeof(show_timing_values) / sizeof(show_timing_values[0])))
+ {
+ return;
+ }
+
+ show_timing = show_timing_values[index];
+ write_config_file();
+ sync_preference_widgets();
+ invalidate_render_caches(TRUE, TRUE, TRUE);
+ gtk_widget_queue_draw(main_window);
+}
+
+void settings_toggle_show_good(GtkWidget *w, gpointer data)
+{
+ if (updating_preferences)
+ {
+ return;
+ }
+
+ show_good_data = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)) ? 1 : 0;
+ write_config_file();
+ sync_preference_widgets();
+ invalidate_render_caches(TRUE, TRUE, TRUE);
+ gtk_widget_queue_draw(main_window);
+}
+
+void settings_toggle_show_bad(GtkWidget *w, gpointer data)
+{
+ if (updating_preferences)
+ {
+ return;
+ }
+
+ show_bad_head = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)) ? 1 : 0;
+ write_config_file();
+ sync_preference_widgets();
+ invalidate_render_caches(TRUE, TRUE, TRUE);
+ gtk_widget_queue_draw(main_window);
+}
+
+void settings_toggle_show_domain(GtkWidget *w, gpointer data)
+{
+ if (updating_preferences)
+ {
+ return;
+ }
+
+ show_domain = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)) ? 1 : 0;
+ write_config_file();
+ sync_preference_widgets();
+ invalidate_render_caches(TRUE, TRUE, TRUE);
+ gtk_widget_queue_draw(main_window);
+}
+
+void settings_toggle_follow_current(GtkWidget *w, gpointer data)
+{
+ if (updating_preferences)
+ {
+ return;
+ }
+
+ follow_current_on_update = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)) ? 1 : 0;
+ write_config_file();
+ sync_preference_widgets();
+}
+
+void jump_to_current(GtkWidget *w, gpointer data)
+{
+ if (total_size <= 0 || main_square_size <= 0 || main_scrolled_window == NULL)
+ {
+ return;
+ }
+
+ int columns = main_drawing_area_width / main_square_size;
+ int rows = main_drawing_area_height / main_square_size;
+ int squares = columns * rows;
+ if (columns <= 0 || rows <= 0 || squares <= 0)
+ {
+ return;
+ }
+
+ long long blocks_per_square = total_size / (squares - 1);
+ int adjustment = 1;
+ while (total_size > squares * blocks_per_square && (squares - adjustment) > 0)
+ {
+ adjustment++;
+ blocks_per_square = total_size / (squares - adjustment);
+ }
+ if (blocks_per_square <= 0)
+ {
+ blocks_per_square = 1;
+ }
+
+ long long current_square = current_position / blocks_per_square;
+ int current_row = current_square / columns;
+ int current_col = current_square % columns;
+ gdouble target = (current_row * main_square_size) - (main_scrolled_window_height / 2.0) + (main_square_size / 2.0);
+
+ GtkAdjustment *vadj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(main_scrolled_window));
+ gdouble lower = gtk_adjustment_get_lower(vadj);
+ gdouble upper = gtk_adjustment_get_upper(vadj) - gtk_adjustment_get_page_size(vadj);
+ if (upper < lower)
+ {
+ upper = lower;
+ }
+ if (target < lower)
+ {
+ target = lower;
+ }
+ if (target > upper)
+ {
+ target = upper;
+ }
+
+ mouse_x = (current_col * main_square_size) + square_adjust + (main_square_size / 2);
+ mouse_y = (current_row * main_square_size) + square_adjust + (main_square_size / 2);
+ mouse_x_old = mouse_x - 1;
+ mouse_y_old = mouse_y - 1;
+
+ gtk_adjustment_set_value(vadj, target);
+ invalidate_render_caches(FALSE, TRUE, FALSE);
gtk_widget_queue_draw(main_window);
}
@@ -3226,6 +3819,7 @@ int print_gui_error_message(char *message, char *title, int type)
void show_settings_window(void)
{
+ sync_preference_widgets();
gtk_widget_show_all(settings_window);
GdkRGBA good_color_rgba;
@@ -3357,6 +3951,8 @@ void set_color(GtkWidget *widget, gpointer data)
}
write_config_file();
+ invalidate_render_caches(TRUE, TRUE, TRUE);
+ gtk_widget_queue_draw(main_window);
}
void read_config_file(void)
@@ -3460,6 +4056,53 @@ void read_config_file(void)
}
}
+ // view settings
+ group = config_setting_get_member(root, "view");
+ if (group != NULL)
+ {
+ setting = config_setting_get_member(group, "main_grid_size");
+ if (setting != NULL)
+ {
+ main_grid_size = config_setting_get_int(setting);
+ }
+
+ setting = config_setting_get_member(group, "auto_update_interval");
+ if (setting != NULL)
+ {
+ auto_update_interval = config_setting_get_int(setting);
+ }
+
+ setting = config_setting_get_member(group, "show_good_data");
+ if (setting != NULL)
+ {
+ show_good_data = config_setting_get_int(setting);
+ }
+
+ setting = config_setting_get_member(group, "show_bad_head");
+ if (setting != NULL)
+ {
+ show_bad_head = config_setting_get_int(setting);
+ }
+
+ setting = config_setting_get_member(group, "show_timing");
+ if (setting != NULL)
+ {
+ show_timing = config_setting_get_int(setting);
+ }
+
+ setting = config_setting_get_member(group, "show_domain");
+ if (setting != NULL)
+ {
+ show_domain = config_setting_get_int(setting);
+ }
+
+ setting = config_setting_get_member(group, "follow_current_on_update");
+ if (setting != NULL)
+ {
+ follow_current_on_update = config_setting_get_int(setting);
+ }
+ }
+
config_destroy(&config);
fclose(config_file);
@@ -3533,6 +4176,30 @@ void write_config_file(void)
config_setting_set_format(setting, CONFIG_FORMAT_HEX);
config_setting_set_int(setting, selected_color);
+ // view settings
+ group = config_setting_add(root, "view", CONFIG_TYPE_GROUP);
+
+ setting = config_setting_add(group, "main_grid_size", CONFIG_TYPE_INT);
+ config_setting_set_int(setting, main_grid_size);
+
+ setting = config_setting_add(group, "auto_update_interval", CONFIG_TYPE_INT);
+ config_setting_set_int(setting, auto_update_interval);
+
+ setting = config_setting_add(group, "show_good_data", CONFIG_TYPE_INT);
+ config_setting_set_int(setting, show_good_data);
+
+ setting = config_setting_add(group, "show_bad_head", CONFIG_TYPE_INT);
+ config_setting_set_int(setting, show_bad_head);
+
+ setting = config_setting_add(group, "show_timing", CONFIG_TYPE_INT);
+ config_setting_set_int(setting, show_timing);
+
+ setting = config_setting_add(group, "show_domain", CONFIG_TYPE_INT);
+ config_setting_set_int(setting, show_domain);
+
+ setting = config_setting_add(group, "follow_current_on_update", CONFIG_TYPE_INT);
+ config_setting_set_int(setting, follow_current_on_update);
+
config_write(&config, config_file);
config_destroy(&config);
diff --git a/src/oscviewer/oscviewer.glade b/src/oscviewer/oscviewer.glade
index ace5e23..f4735bd 100644
--- a/src/oscviewer/oscviewer.glade
+++ b/src/oscviewer/oscviewer.glade
@@ -89,6 +89,13 @@
@@ -1292,6 +1306,287 @@
13
+
+
+
+ False
+ True
+ 14
+
+
+
+
+
+ False
+ True
+ 15
+
+
+
+
+
+ False
+ True
+ 16
+
+
+
+
+ True
+ False
+
+
+ True
+ False
+ 10
+ Auto-Update
+ 0
+
+
+ True
+ True
+ 0
+
+
+
+
+ True
+ True
+
+
+ False
+ True
+ 1
+
+
+
+
+ False
+ True
+ 17
+
+
+
+
+ True
+ False
+
+
+ True
+ False
+ 10
+ Show High-Time
+ 0
+
+
+ True
+ True
+ 0
+
+
+
+
+ True
+ True
+
+
+ False
+ True
+ 1
+
+
+
+
+ False
+ True
+ 18
+
+
+
+
+ True
+ False
+
+
+ True
+ False
+ 10
+ Highlight Good Data
+ 0
+
+
+ True
+ True
+ 0
+
+
+
+
+ True
+ True
+ True
+
+
+ False
+ True
+ 1
+
+
+
+
+ False
+ True
+ 19
+
+
+
+
+ True
+ False
+
+
+ True
+ False
+ 10
+ Show Bad Head
+ 0
+
+
+ True
+ True
+ 0
+
+
+
+
+ True
+ True
+ True
+
+
+ False
+ True
+ 1
+
+
+
+
+ False
+ True
+ 20
+
+
+
+
+ True
+ False
+
+
+ True
+ False
+ 10
+ Show Domain
+ 0
+
+
+ True
+ True
+ 0
+
+
+
+
+ True
+ True
+ True
+
+
+ False
+ True
+ 1
+
+
+
+
+ False
+ True
+ 21
+
+
+
+
+ True
+ False
+
+
+ True
+ False
+ 10
+ Follow Current on Auto-Update
+ 0
+
+
+ True
+ True
+ 0
+
+
+
+
+ True
+ True
+ True
+
+
+ False
+ True
+ 1
+
+
+
+
+ False
+ True
+ 22
+
+
diff --git a/src/oscviewer/oscviewer.h b/src/oscviewer/oscviewer.h
index dd3f530..386744d 100644
--- a/src/oscviewer/oscviewer.h
+++ b/src/oscviewer/oscviewer.h
@@ -103,6 +103,23 @@ GtkWidget *left_drawing_area;
GtkWidget *main_scrolled_window;
GtkWidget *main_drawing_vbox;
+// cached render surfaces
+cairo_surface_t *top_render_cache;
+cairo_surface_t *main_render_cache;
+cairo_surface_t *left_render_cache;
+gboolean top_render_cache_dirty;
+gboolean main_render_cache_dirty;
+gboolean left_render_cache_dirty;
+gint top_render_cache_width;
+gint top_render_cache_height;
+gint main_render_cache_width;
+gint main_render_cache_height;
+gdouble main_render_cache_scroll_position;
+gint main_render_cache_clip_x;
+gint main_render_cache_clip_y;
+gint left_render_cache_width;
+gint left_render_cache_height;
+
// main window widgets
GtkWidget *progress_log_label;
GtkWidget *domain_log_label;
@@ -134,6 +151,14 @@ GtkWidget *time_color_label;
GtkWidget *domain_color_label;
GtkWidget *block_color_label;
GtkWidget *marker_color_label;
+GtkWidget *settings_view_label;
+GtkWidget *settings_main_grid_size_combo;
+GtkWidget *settings_auto_update_combo;
+GtkWidget *settings_show_good_data_check;
+GtkWidget *settings_show_bad_head_check;
+GtkWidget *settings_show_domain_check;
+GtkWidget *settings_show_timing_combo;
+GtkWidget *settings_follow_current_check;
// file menu
GtkWidget *filemenu;
@@ -179,6 +204,7 @@ GtkWidget *mainsizebutton2m;
GtkWidget *mainsizebutton4m;
GtkWidget *mainsizebutton8m;
GtkWidget *mainsizebutton16m;
+GtkWidget *jumpcurrentmi;
GtkWidget *autoupdatemi;
GtkWidget *autoupdatemenu;
GtkWidget *autoupdatebuttonoff;
@@ -190,6 +216,7 @@ GtkWidget *autoupdatebutton2m;
GtkWidget *autoupdatebutton5m;
GtkWidget *showbadcheck;
GtkWidget *showdomaincheck;
+GtkWidget *followcurrentcheck;
GtkWidget *optionsw;
GSList *leftresgroup = NULL;
GSList *mainresgroup = NULL;
@@ -276,12 +303,15 @@ int selected_color = WHITE;
int time_color = MAGENTA;
int domain_color = MYBLUE;
int main_grid_size = MAINGRIDSIZE;
+int auto_update_interval = 0;
gint timeout_tag = 0;
int autotimer_on = 0;
int show_bad_head = 0;
int show_good_data = 0;
int show_timing = 0;
int show_domain = 0;
+int follow_current_on_update = 0;
+gboolean updating_preferences = FALSE;
int mouse_x = 0;
int mouse_y = 0;
int mouse_x_old = 0;
@@ -301,6 +331,10 @@ static gboolean left_drawing_expose_event(GtkWidget *self, cairo_t *cr, gpointer
static gboolean top_drawing_expose_event(GtkWidget *self, cairo_t *cr, gpointer user_data);
+static void invalidate_render_caches(gboolean top_dirty, gboolean main_dirty, gboolean left_dirty);
+
+static void clear_render_cache(cairo_surface_t **surface, gint *width, gint *height);
+
void getsize_top_drawing_area(GtkWidget *widget, GtkAllocation *allocation, void *data);
void getsize_main_drawing_area(GtkWidget *widget, GtkAllocation *allocation, void *data);
@@ -315,8 +349,24 @@ void change_main_resolution(GtkWidget *w, gpointer data);
void change_main_grid_size(GtkWidget *w, gpointer data);
+void settings_main_grid_size_changed(GtkWidget *w, gpointer data);
+
+void settings_auto_update_changed(GtkWidget *w, gpointer data);
+
+void settings_show_timing_changed(GtkWidget *w, gpointer data);
+
+void settings_toggle_show_good(GtkWidget *w, gpointer data);
+
+void settings_toggle_show_bad(GtkWidget *w, gpointer data);
+
+void settings_toggle_show_domain(GtkWidget *w, gpointer data);
+
+void settings_toggle_follow_current(GtkWidget *w, gpointer data);
+
void change_left_resolution(GtkWidget *w, gpointer data);
+void jump_to_current(GtkWidget *w, gpointer data);
+
int initialize_memory(void);
int increase_log_memory(int new_lines);
@@ -361,6 +411,8 @@ void set_show_timing(GtkWidget *w, gpointer data);
void toggle_showdomain(GtkWidget *w, gpointer data);
+void toggle_follow_current_menu(GtkWidget *w, gpointer data);
+
int check_log(void);
void select_file(void);