#define _XOPEN_SOURCE /* glibc2 needs this */ #include #include #include #include #include #include #define _GNU_SOURCE #include #include #include #define SECOND_INTERVAL 1000 #define DEFAULT_WIDTH 200 #define DEFAULT_HEIGHT 15 struct private { time_t time; time_t von_arrives; struct timeval tv_now; gchar *ts; gchar *msg; gfloat s; }; static gboolean time_handler (GtkWidget* w) { gtk_widget_queue_draw (w); return TRUE; } gboolean on_key_press (GtkWidget *widget, GdkEventKey *key, gpointer p) { if (key->type == GDK_KEY_PRESS) { switch (key->keyval) { case GDK_Escape : gtk_main_quit (); break; } } return FALSE; } static void paint (GtkWidget *widget, GdkEventExpose *eev, struct private *p) { gint width, height; cairo_t *cr; gint sec, min, hour, day; p->time = p->von_arrives - time(NULL); gettimeofday(&p->tv_now, NULL); localtime (&p->tv_now.tv_sec); day = p->time / (3600*24); p->time -= day*(3600*24); hour = p->time / 3600; p->time -= hour*3600; min = p->time/60; p->time -= min*60; sec = p->time; g_sprintf(p->ts, "Von arrives in %02dd %02d:%02d:%02d:%02d", day, hour, min, sec, (int) (99 - ((p->tv_now.tv_usec)/10e3))); width = widget->allocation.width; height = widget->allocation.height; cr = gdk_cairo_create (widget->window); cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); cairo_set_source_rgba (cr, 1.0f, 1.0f, 1.0f, 0.4f); cairo_paint (cr); cairo_select_font_face (cr, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); cairo_save (cr); cairo_set_font_size (cr, 10*p->s); cairo_move_to (cr, 10*p->s, 10*p->s); cairo_set_source_rgba (cr, 0.0f, 0.0f, 0.0f, 1.0f); cairo_show_text (cr, p->ts); cairo_restore (cr); cairo_destroy (cr); } static void install_colormap (GtkWidget *w) { GdkScreen* screen = gtk_widget_get_screen (w); GdkColormap* colormap = gdk_screen_get_rgba_colormap (screen); if (!colormap) colormap = gdk_screen_get_rgb_colormap (screen); gtk_widget_set_colormap (w, colormap); } inline int parse_time (char *time, char *fmt, struct tm *tm) { char *s_res = NULL; if (time) { if ((s_res = strptime(time, fmt, tm)) == NULL) { printf("WARNING: couldn't parse time '%s' with format '%s'.\n", time, fmt); return -1; } if (*s_res != '\0') { printf("WARNING: processing stoped at '%s'\n", s_res); return time - s_res; } return 0; } return -2; } gint usage (char *name) { return printf ("usage: %s [TIME[+FMT]].\n", name); } #define DFMT "%Y-%m-%d" #define SFMT "%H:%M" gint main (gint argc, gchar **argv) { int c, option_index = 0; static struct option long_options[] ={ {"date", 1, 0, 'd'}, {"time", 1, 0, 't'}, {"format", 1, 0, 'f'}, {"size", 1, 0, 's'}, {"help", 0, 0, 'h'}, {0, 0, 0, 0} }; char *s_time = NULL; char *s_full = NULL; char *s_date = NULL; char *s_dfmt = DFMT; char *s_tfmt = SFMT; char *s_fmt = DFMT "-" SFMT; /* HACK HERE */ GtkWidget *window; struct private *p = malloc(sizeof(struct private)); struct tm von_time = { .tm_min = 40, .tm_hour = 9, .tm_mday = 14, .tm_mon = 1, .tm_year = 107, }; while ((c = getopt_long (argc, argv, "d:t:f:s:h", long_options, &option_index)) != -1) { switch (c) { case 'd': s_date = optarg; break; case 't': s_time = optarg; break; case 'f': s_fmt = optarg; break; case 's': p->s = strtod(optarg, NULL); break; case 'h': case '?': return usage(argv[0]); default: printf ("given %d (%c)\n", c, c); } } for (;optind < argc; optind++) { switch (*argv[optind]) { case '+': s_fmt = argv[optind] + 1; break; default: if (s_time != NULL) printf ("WARNING: overriding previously given time \n" "'%s'\n" "with '%s'.\n", s_time, argv[optind]); s_full = argv[optind]; } } parse_time(s_date, s_dfmt, &von_time); parse_time(s_time, s_tfmt, &von_time); parse_time(s_full, s_fmt, &von_time); if (time(NULL) > mktime(&von_time)) printf("WARNING: given a date in the past !\n"); p->ts = g_strdup_printf("Von arrives in 00d 00:00:00:00"); p->von_arrives = mktime(&von_time); gtk_init(&argc, &argv); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_window_stick (GTK_WINDOW (window)); gtk_window_set_keep_below (GTK_WINDOW (window), TRUE); gtk_window_set_skip_taskbar_hint (GTK_WINDOW (window), TRUE); gtk_window_set_skip_pager_hint (GTK_WINDOW (window), TRUE); gtk_window_set_accept_focus (GTK_WINDOW (window), FALSE); gtk_window_set_decorated (GTK_WINDOW (window), FALSE); gtk_window_set_resizable (GTK_WINDOW (window), TRUE); gtk_widget_set_app_paintable (window, TRUE); gtk_window_set_default_size (GTK_WINDOW (window), DEFAULT_WIDTH*p->s, DEFAULT_HEIGHT*p->s); install_colormap(window); gtk_widget_add_events (window, GDK_BUTTON_PRESS_MASK); g_signal_connect (G_OBJECT (window), "expose-event", G_CALLBACK (paint), p); g_signal_connect (G_OBJECT (window), "key-press-event", G_CALLBACK (on_key_press), NULL); gtk_widget_show_all (window); gtk_timeout_add (SECOND_INTERVAL/9, (GtkFunction) time_handler, window); gtk_main (); g_free(p->ts); free(p); return 0; }