32 #include <glib/gi18n.h> 34 #include "dialog-utils.h" 39 #define GNC_PREFS_GROUP "dialogs.flicker" 40 #define GNC_STATE_SECTION "Flicker" 41 #define STATE_KEY_BAR_WIDTH "barwidth" 42 #define STATE_KEY_DELAY "delay" 45 #define BAR_HEIGHT 200 49 static guint flicker_data (
char const *challenge);
50 static gboolean time_handler (GtkWidget *widget);
51 static void do_marker_drawing (cairo_t *cr);
52 static void draw_bit (cairo_t *cr, _Bool bit,
int i);
53 static void do_flicker_drawing (GtkWidget *widget, cairo_t *cr);
54 static void do_flicker_load_state (GtkWidget *dialog);
55 static void do_flicker_store_state (GtkWidget *dialog);
56 static gboolean on_flicker_challenge_draw (GtkWidget *widget, cairo_t *cr,
58 static void on_flicker_challenge_map (GtkWidget *widget);
59 static void on_flicker_challenge_destroy (GtkWidget *widget, gpointer user_data);
60 static gboolean on_flicker_marker_draw (GtkWidget *widget, cairo_t *cr,
62 static void on_flicker_marker_map (GtkWidget *widget);
63 static void on_spin_barwidth_value_changed (GtkSpinButton *spin, GtkWidget *widget);
64 static void on_spin_delay_value_changed (GtkSpinButton *spin, GtkWidget *widget);
65 static void on_dialog_destroy (GtkWidget *dialog, gpointer user_data);
69 const char *challenge;
70 guint challenge_length;
84 gboolean change_interval;
89 static _Bool bitarray[255][5];
93 get_num (
const char ch)
96 if (ch >=
'0' && ch <=
'9')
102 case 'A':
case 'a': num = 10;
break;
103 case 'B':
case 'b': num = 11;
break;
104 case 'C':
case 'c': num = 12;
break;
105 case 'D':
case 'd': num = 13;
break;
106 case 'E':
case 'e': num = 14;
break;
107 case 'F':
case 'f': num = 15;
break;
118 flicker_data (
const char *challenge)
123 static const _Bool bits[16][5] =
125 {0, 0, 0, 0, 0}, {0, 1, 0, 0, 0}, {0, 0, 1, 0, 0}, {0, 1, 1, 0, 0},
126 {0, 0, 0, 1, 0}, {0, 1, 0, 1, 0}, {0, 0, 1, 1, 0}, {0, 1, 1, 1, 0},
127 {0, 0, 0, 0, 1}, {0, 1, 0, 0, 1}, {0, 0, 1, 0, 1}, {0, 1, 1, 0, 1},
128 {0, 0, 0, 1, 1}, {0, 1, 0, 1, 1}, {0, 0, 1, 1, 1}, {0, 1, 1, 1, 1}
132 char* code = g_strdup_printf (
"0FFF%s", challenge);
133 guint challenge_length = strlen (code);
137 for (guint i = 0; i < challenge_length; i += 2)
139 guint val1 = get_num (code[i]);
140 guint val2 = get_num (code[i+1]);
142 memcpy (&bitarray[i], bits[val2],
sizeof(bits[val2]));
143 memcpy (&bitarray[i+1], bits[val1],
sizeof(bits[val1]));
147 return challenge_length;
153 time_handler (GtkWidget *widget)
156 if (flickerdraw.change_interval)
158 g_source_remove (flickerdraw.interval);
159 flickerdraw.interval = g_timeout_add (flickerdraw.delay,
160 (GSourceFunc) time_handler,
162 flickerdraw.change_interval = FALSE;
165 gtk_widget_queue_draw (widget);
172 do_marker_drawing (cairo_t *cr)
178 cairo_set_source_rgb (cr, 0, 0, 0);
181 cairo_set_source_rgb (cr, 0.9, 0.1, 0.1);
183 pos1 = flickerdraw.x_drawpos + flickerdraw.barwidth / 2;
184 cairo_move_to (cr, pos1, 20);
185 cairo_line_to (cr, pos1 + 10, 2);
186 cairo_line_to (cr, pos1 - 10, 2);
187 cairo_close_path (cr);
188 cairo_stroke_preserve (cr);
192 pos2 = flickerdraw.x_drawpos + 4 * flickerdraw.margin + 4 * flickerdraw.barwidth +
193 flickerdraw.barwidth / 2;
194 cairo_move_to (cr, pos2, 20);
195 cairo_line_to (cr, pos2 + 10, 2);
196 cairo_line_to (cr, pos2 - 10, 2);
197 cairo_close_path (cr);
198 cairo_stroke_preserve (cr);
204 draw_bit (cairo_t *cr, _Bool bit,
int i)
207 cairo_set_source_rgb (cr, 1, 1, 1);
209 cairo_set_source_rgb (cr, 0, 0, 0);
211 flickerdraw.x_barpos = flickerdraw.x_drawpos + i * flickerdraw.margin +
212 i * flickerdraw.barwidth;
213 cairo_rectangle (cr, flickerdraw.x_barpos, flickerdraw.y_barpos,
214 flickerdraw.barwidth, flickerdraw.barheight);
220 do_flicker_drawing (GtkWidget *widget, cairo_t *cr)
223 flickerdraw.width = gtk_widget_get_allocated_width (widget);
226 flickerdraw.x_drawpos = (flickerdraw.width - 4 * flickerdraw.margin -
227 5 * flickerdraw.barwidth) / 2;
230 cairo_set_source_rgb (cr, 0, 0, 0);
234 bitarray[flickerdraw.halfbyteid][0] = flickerdraw.clock;
235 draw_bit (cr, flickerdraw.clock, 0);
236 for (
int i = 1; i <= 4; i++)
237 draw_bit (cr, bitarray[flickerdraw.halfbyteid][i], i);
240 if (!flickerdraw.clock)
242 flickerdraw.clock = 1;
243 flickerdraw.halfbyteid++;
244 if (flickerdraw.halfbyteid >= flickerdraw.challenge_length)
245 flickerdraw.halfbyteid = 0;
247 else if (flickerdraw.clock)
248 flickerdraw.clock = 0;
253 do_flicker_load_state (GtkWidget *dialog)
258 if (g_key_file_has_key (state_file, GNC_STATE_SECTION, STATE_KEY_BAR_WIDTH, NULL))
259 flickerdraw.barwidth = g_key_file_get_integer (state_file,
261 STATE_KEY_BAR_WIDTH, NULL);
263 flickerdraw.barwidth = BAR_WIDTH;
265 if (g_key_file_has_key (state_file, GNC_STATE_SECTION, STATE_KEY_DELAY, NULL))
266 flickerdraw.delay = g_key_file_get_integer (state_file,
268 STATE_KEY_DELAY, NULL);
270 flickerdraw.delay = DELAY;
273 gnc_restore_window_size (GNC_PREFS_GROUP, GTK_WINDOW (dialog),
279 do_flicker_store_state (GtkWidget *dialog)
284 if (flickerdraw.barwidth != BAR_WIDTH)
285 g_key_file_set_integer (state_file, GNC_STATE_SECTION,
286 STATE_KEY_BAR_WIDTH, flickerdraw.barwidth);
287 else if (g_key_file_has_key (state_file, GNC_STATE_SECTION,
288 STATE_KEY_BAR_WIDTH, NULL))
289 g_key_file_remove_key (state_file, GNC_STATE_SECTION,
290 STATE_KEY_BAR_WIDTH, NULL);
292 if (flickerdraw.delay != DELAY)
293 g_key_file_set_integer (state_file, GNC_STATE_SECTION,
294 STATE_KEY_DELAY, flickerdraw.delay);
295 else if (g_key_file_has_key (state_file, GNC_STATE_SECTION,
296 STATE_KEY_DELAY, NULL))
297 g_key_file_remove_key (state_file, GNC_STATE_SECTION,
298 STATE_KEY_DELAY, NULL);
301 gnc_save_window_size (GNC_PREFS_GROUP, GTK_WINDOW (dialog));
306 on_flicker_challenge_map (GtkWidget *widget)
308 flickerdraw.challenge_length = flicker_data (flickerdraw.challenge);
311 flickerdraw.height = flickerdraw.barheight + 2 * flickerdraw.y_barpos;
312 gtk_widget_set_size_request (widget, -1, flickerdraw.height);
315 flickerdraw.interval = g_timeout_add (flickerdraw.delay,
316 (GSourceFunc) time_handler,
322 on_flicker_challenge_draw (GtkWidget *widget, cairo_t *cr,
323 __attribute__((unused)) gpointer user_data)
325 do_flicker_drawing (widget, cr);
332 on_flicker_challenge_destroy (GtkWidget *widget,
333 __attribute__((unused)) gpointer user_data)
336 g_source_remove (flickerdraw.interval);
342 on_flicker_marker_draw (__attribute__((unused)) GtkWidget *widget, cairo_t *cr,
343 __attribute__((unused)) gpointer data)
345 do_marker_drawing (cr);
352 on_flicker_marker_map (GtkWidget *widget)
355 gtk_widget_set_size_request (widget, -1, flickerdraw.y_barpos);
361 on_spin_barwidth_value_changed (GtkSpinButton *spin, GtkWidget *widget)
363 flickerdraw.barwidth = gtk_spin_button_get_value_as_int (spin);
364 flickerdraw.x_drawpos = (flickerdraw.width - 4 * flickerdraw.margin -
365 5 * flickerdraw.barwidth) / 2;
368 gtk_widget_queue_draw (widget);
374 on_spin_delay_value_changed (GtkSpinButton *spin, GtkWidget *widget)
376 flickerdraw.delay = gtk_spin_button_get_value_as_int (spin);
378 flickerdraw.change_interval = TRUE;
379 time_handler (widget);
383 on_dialog_destroy (GtkWidget *dialog, __attribute__((unused)) gpointer user_data)
386 do_flicker_store_state (dialog);
397 do_flicker_load_state (GTK_WIDGET (flickergui->dialog));
400 flickerdraw.barheight = BAR_HEIGHT;
401 flickerdraw.margin = MARGIN;
402 flickerdraw.y_barpos = 20;
403 flickerdraw.halfbyteid = 0;
404 flickerdraw.clock = 1;
406 flickerdraw.challenge = pChallenge;
408 g_signal_connect (GTK_WINDOW (flickergui->dialog),
"destroy",
409 G_CALLBACK (on_dialog_destroy), NULL);
411 g_signal_connect (GTK_WIDGET (flickergui->flicker_challenge),
"map",
412 G_CALLBACK (on_flicker_challenge_map), NULL);
413 g_signal_connect (GTK_WIDGET (flickergui->flicker_challenge),
"draw",
414 G_CALLBACK (on_flicker_challenge_draw), NULL);
415 g_signal_connect (GTK_WIDGET (flickergui->flicker_challenge),
"destroy",
416 G_CALLBACK (on_flicker_challenge_destroy), NULL);
418 g_signal_connect (GTK_WIDGET (flickergui->flicker_marker),
"map",
419 G_CALLBACK (on_flicker_marker_map), NULL);
420 g_signal_connect (GTK_WIDGET (flickergui->flicker_marker),
"draw",
421 G_CALLBACK (on_flicker_marker_draw), NULL);
423 flickergui->adj_barwidth = gtk_adjustment_new (0.0, 10.0, 80.0, 1.0, 10.0, 0.0);
424 gtk_spin_button_set_adjustment (flickergui->spin_barwidth, flickergui->adj_barwidth);
425 gtk_spin_button_set_value (GTK_SPIN_BUTTON (flickergui->spin_barwidth),
426 flickerdraw.barwidth);
427 g_signal_connect (GTK_WIDGET (flickergui->spin_barwidth),
"value-changed",
428 G_CALLBACK (on_spin_barwidth_value_changed),
429 flickergui->flicker_marker);
430 gtk_widget_set_focus_on_click (GTK_WIDGET (flickergui->spin_barwidth), FALSE);
432 flickergui->adj_delay = gtk_adjustment_new (0.0, 10.0, 100.0, 10.0, 10.0, 0.0);
433 gtk_spin_button_set_adjustment (flickergui->spin_delay, flickergui->adj_delay);
434 gtk_spin_button_set_value (GTK_SPIN_BUTTON (flickergui->spin_delay),
436 g_signal_connect (GTK_WIDGET (flickergui->spin_delay),
"value-changed",
437 G_CALLBACK (on_spin_delay_value_changed),
438 flickergui->flicker_challenge);
439 gtk_widget_set_focus_on_click (GTK_WIDGET (flickergui->spin_delay), FALSE);
441 gtk_widget_grab_focus (GTK_WIDGET (flickergui->input_entry));
Functions to load, save and get gui state.
GtkWindow * gnc_ui_get_main_window(GtkWidget *widget)
Get a pointer to the final GncMainWindow widget is rooted in.
GKeyFile * gnc_state_get_current(void)
Returns a pointer to the most recently loaded state.
GUI callbacks for Flicker and ChipTAN(optisch)
void ini_flicker_gui(const char *pChallenge, GncFlickerGui *gui)
Initialize the dialog and drawing area.