/*
* Trivial Tea Timer
*
- * (c) 2002, 2010 Martin Mares <mj@ucw.cz>
+ * (c) 2002, 2010, 2013 Martin Mares <mj@ucw.cz>
+ * (c) 2021 Jiri Kalvoda <jirikalvoda@kam.mff.cuni.cz>
*
* GPL'ed
*/
#define UNUSED __attribute__((unused))
static guint second_timer;
-static char old_text[8];
-static GtkWidget *win, *hbox1, *timebox, *togglebutton1;
+static char old_text[16];
+static GtkWidget *win, *hbox1, *vbox1, *timebox, *namebox, *togglebutton1;
static time_t alarm_time;
static char *run_cmd;
static int expired;
+static void
+expand_and_exec(char *cmd)
+{
+ GString * expanded_cmd = g_string_new("");
+ for (int i=0; cmd[i]; i++)
+ {
+ if (cmd[i]=='%' && cmd[i+1]=='%')
+ {
+ i++;
+ g_string_append_c(expanded_cmd, '%');
+ }
+ else
+ if (cmd[i]=='%' && cmd[i+1]=='n')
+ {
+ i++;
+ const gchar * name = gtk_entry_get_text(GTK_ENTRY(namebox));
+ g_string_append(expanded_cmd, name);
+ }
+ else
+ g_string_append_c(expanded_cmd, cmd[i]);
+ }
+
+ GError *err = NULL;
+ g_spawn_command_line_async(expanded_cmd->str, &err);
+ g_string_free(expanded_cmd, 1);
+ if (err)
+ {
+ fprintf(stderr, "teatimer: Unable to run command: %s\n", err->message);
+ g_error_free(err);
+ }
+}
+
static void
it_tolls_for_thee(void)
{
{
if (!expired)
{
- GError *err = NULL;
- g_spawn_command_line_async(run_cmd, &err);
- if (err)
- {
- fprintf(stderr, "teatimer: Unable to run command: %s\n", err->message);
- g_error_free(err);
- }
+ expand_and_exec(run_cmd);
expired = 1;
}
}
static gint
on_second_timeout(gpointer data UNUSED)
{
- char buf[8];
+ char buf[16];
time_t now = time(NULL);
int delta = alarm_time - now;
char *sign = "";
sign = "-";
delta = -delta;
}
- if (delta >= 6000)
- delta = 5999;
- sprintf(buf, "%s%02d:%02d", sign, delta/60, delta%60);
+ if (delta >= 100*60*60)
+ delta = 100*60*60 - 1;
+ if (delta < 60*60)
+ sprintf(buf, "%s%02d:%02d", sign, delta/60, delta%60);
+ else
+ sprintf(buf, "%s%02d:%02d:%02d", sign, delta/3600, (delta%3600)/60, delta%60);
gtk_entry_set_text(GTK_ENTRY(timebox), buf);
if (now >= alarm_time)
it_tolls_for_thee();
}
static gint
-on_timebox_key(GtkWidget *widget UNUSED, GdkEventKey *ev, gpointer user_data UNUSED)
+on_box_key(GtkWidget *widget UNUSED, GdkEventKey *ev, gpointer user_data UNUSED)
{
if (!strcmp(ev->string, "\r"))
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(togglebutton1), !GTK_TOGGLE_BUTTON(togglebutton1)->active);
parse_time(char *c)
{
int t = 0;
+ int parts = 0;
- while (*c && *c != ':')
+ while (*c)
{
- if (*c >= '0' && *c <= '9')
- t = 10*t + *c++ - '0';
- else
+ parts++;
+ if (parts > 3)
return -1;
- }
- if (*c)
- {
int m = 0;
- c++;
- while (*c)
+ while (*c >= '0' && *c <= '9')
+ m = 10*m + *c++ - '0';
+ t += m;
+ if (*c == ':')
{
- if (*c >= '0' && *c <= '9')
- m = 10*m + *c++ - '0';
- else
- return -1;
+ c++;
+ t = 60*t;
}
- t = 60*t + m;
+ else if (*c)
+ return -1;
}
- if (t >= 6000)
+
+ if (!parts)
+ return -1;
+ if (t >= 100*60*60)
return -1;
return t;
}
}
gtk_entry_set_text(GTK_ENTRY(timebox), old_text);
gtk_entry_set_editable(GTK_ENTRY(timebox), 1);
- gtk_widget_grab_focus (timebox);
+ gtk_widget_grab_focus(timebox);
}
}
static void
open_window(void)
{
- win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- gtk_window_set_title (GTK_WINDOW (win), "Tea Timer");
- gtk_window_set_policy (GTK_WINDOW (win), TRUE, TRUE, TRUE);
+ win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title(GTK_WINDOW (win), "Tea Timer");
+ gtk_window_set_policy(GTK_WINDOW (win), TRUE, TRUE, TRUE);
+
+ hbox1 = gtk_hbox_new(FALSE, 0);
+ gtk_widget_show(hbox1);
+ gtk_container_add(GTK_CONTAINER (win), hbox1);
+
+ vbox1 = gtk_vbox_new(FALSE, 0);
+ gtk_widget_show(vbox1);
+ gtk_box_pack_start(GTK_BOX(hbox1), vbox1, TRUE, TRUE, 0);
+
+ namebox = gtk_entry_new_with_max_length(30);
+ gtk_widget_show(namebox);
+ gtk_box_pack_start(GTK_BOX(vbox1), namebox, TRUE, TRUE, 0);
+ gtk_entry_set_text(GTK_ENTRY(namebox), "Tea");
- hbox1 = gtk_hbox_new (FALSE, 0);
- gtk_widget_show (hbox1);
- gtk_container_add (GTK_CONTAINER (win), hbox1);
+ timebox = gtk_entry_new_with_max_length(9);
+ gtk_widget_show(timebox);
+ gtk_box_pack_start(GTK_BOX(vbox1), timebox, TRUE, TRUE, 0);
+ gtk_entry_set_text(GTK_ENTRY(timebox), "00:00");
- timebox = gtk_entry_new_with_max_length (6);
- gtk_widget_show (timebox);
- gtk_box_pack_start (GTK_BOX (hbox1), timebox, TRUE, TRUE, 0);
- gtk_entry_set_text (GTK_ENTRY (timebox), "00:00");
+ togglebutton1 = gtk_toggle_button_new_with_label("Run");
+ gtk_widget_show(togglebutton1);
+ gtk_box_pack_start(GTK_BOX(hbox1), togglebutton1, FALSE, FALSE, 0);
- togglebutton1 = gtk_toggle_button_new_with_label ("Run");
- gtk_widget_show (togglebutton1);
- gtk_box_pack_start (GTK_BOX (hbox1), togglebutton1, FALSE, FALSE, 0);
+ gtk_signal_connect(GTK_OBJECT(win), "remove", GTK_SIGNAL_FUNC(on_window_remove), NULL);
+ gtk_signal_connect(GTK_OBJECT(namebox), "key_press_event", GTK_SIGNAL_FUNC(on_box_key), NULL);
+ gtk_signal_connect(GTK_OBJECT(timebox), "key_press_event", GTK_SIGNAL_FUNC(on_box_key), NULL);
+ gtk_signal_connect(GTK_OBJECT(togglebutton1), "toggled", GTK_SIGNAL_FUNC(on_togglebutton1_toggled), NULL);
- gtk_signal_connect(GTK_OBJECT (win), "remove", GTK_SIGNAL_FUNC (on_window_remove), NULL);
- gtk_signal_connect(GTK_OBJECT (timebox), "key_press_event", GTK_SIGNAL_FUNC (on_timebox_key), NULL);
- gtk_signal_connect(GTK_OBJECT (togglebutton1), "toggled", GTK_SIGNAL_FUNC (on_togglebutton1_toggled), NULL);
+ gtk_widget_grab_focus(timebox);
- gtk_widget_grab_focus (timebox);
+ // Do not focus button
+ GList *focus_chain = NULL;
+ focus_chain = g_list_append(focus_chain, vbox1);
+ gtk_container_set_focus_chain(GTK_CONTAINER (hbox1), focus_chain);
gtk_widget_show(win);
}
fprintf(stderr, "Usage: teatimer [<options>] [<mm:ss>]\n\n\
Options:\n\
-r, --run=<cmd>\t\tRun a given program when the tea is ready\n\
+\t\t\t\t%%d will be expanded to timer name\n\
+\t\t\t\t%%%% will be expanded to %%\n\
");
exit(1);
}